<rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title>Cybershenanigans Blog</title><link>https://blog.cybershenanigans.space/</link><description>Blog about various technical/cybersecurity topics</description><generator>Hugo -- gohugo.io</generator><language>en-US</language><managingEditor>matthewe2020@gmail.com (Matt Ehrnschwender)</managingEditor><webMaster>matthewe2020@gmail.com (Matt Ehrnschwender)</webMaster><copyright>© 2024 Matt Ehrnschwender, All rights reserved.</copyright><lastBuildDate>Fri, 30 May 2025 00:00:00 +0000</lastBuildDate><atom:link href="https://blog.cybershenanigans.space/index.xml" rel="self" type="application/rss+xml"/><item><title>Boflink: A Linker For Beacon Object Files</title><link>https://blog.cybershenanigans.space/posts/boflink-a-linker-for-beacon-object-files/</link><pubDate>Fri, 30 May 2025 00:00:00 +0000</pubDate><author>Matt Ehrnschwender</author><guid>https://blog.cybershenanigans.space/posts/boflink-a-linker-for-beacon-object-files/</guid><description><![CDATA[<h2 id="intro">Intro</h2>
<p>This is a blog post written for a project I recently released. The source code for it can be found here on <a href="https://github.com/MEhrn00/boflink" target="_blank" rel="noopener noreffer ">Github</a>.</p>
<h2 id="background">Background</h2>
<p>The design of Cobalt Strike’s Beacon Object Files is rather unique when compared to other runtime code execution implementations. These are small programs compiled into COFF object files which are loaded and executed by a COFF loader. Another addition that Beacon Object Files make is the concept of dynamic function resolution or DFR which allows the COFF to invoke functions from external DLLs.</p>
<p>The popularity of Beacon Object Files has exploded since they were first introduced in Cobalt Strike. Due to their popularity, many projects have been released to take advantage of this new technique. TrustedSec released a blog post on <a href="https://trustedsec.com/blog/coffloader-building-your-own-in-memory-loader-or-how-to-run-bofs" target="_blank" rel="noopener noreffer ">developing a Beacon Object File loader</a> shortly after the initial concept was introduced. The blog post and <a href="https://github.com/trustedsec/COFFLoader" target="_blank" rel="noopener noreffer ">COFFLoader</a> implementation made it easier for developers to both develop their own BOFs and also include this capability into their own tools. BOF loaders have become widely adopted by many different red team tools. They can provide a fairly lightweight extension system that is agnostic to the underlying platform which makes BOFs ideal from a developer standpoint.</p>
<p>Although the concept behind BOFs was first introduced back in 2020, the development process and tooling has largely stayed the same. There has been an increase in public project templates for BOF development, such as the <a href="https://github.com/Cobalt-Strike/bof-vs" target="_blank" rel="noopener noreffer ">bof-vs</a> template, which can help with some development aspects.</p>
<p>These templates still suffer some of the same limitations that come with the nature of Beacon Object Files.</p>
<h2 id="current-beacon-object-file-limitations">Current Beacon Object File Limitations</h2>
<p>One of the limitations with BOFs is the way it handles external imports. It uses a method known as DFR which consists of changing the names of imported symbols to include the name of the library the symbol is from. I wrote a previous blog post on the complications that come with this: “<a href="https://blog.cybershenanigans.space/posts/writing-bofs-without-dfr/" target="_blank" rel="noopener noreffer ">Writing Beacon Object Files Without DFR</a>”.</p>
<p>Another design limitation is that BOFs rely on using object files as a “final file format”. The main purpose of object files is to act as an intermediary compilation artifact during the build process rather than a complete file suitable for other uses. This makes the raw object files produced by compilers optimized more for later use by a system linker for building a complete executable file.</p>
<p>Compilers may emit various symbols and other compilation artifacts inside the object file which are useful to the linker but may cause issues if not handled properly by a loader. This results in the loader requiring extra logic to handle these cases in order to make a decision on how to handle certain artifacts depending on the context. If these are not handled properly, it may cause issues where the compiler generated code assumes that the artifact was processed correctly.</p>
<p>Object files are also the product of compiling a single translation unit which typically means a single C or C++ source file. The source can be split up between multiple files but ultimately, these files will have to be combined either through <code>#include</code> statements or by concatenating their contents in order for the compiler to compile it. This can potentially make things difficult to maintain or debug.</p>
<h2 id="introducing-boflink">Introducing Boflink</h2>
<p>Boflink is a tool designed to act as a sort of fill-in for the missing linking stage that comes with the BOF development process. It is a linker that takes unmodified object files generated by a compiler and links them together into a Beacon Object File capable of being loaded by a BOF loader.</p>
<p>Its main goal is to act as a bridge between the BOF development and the BOF loading process to help simplify them.</p>
<p>On the BOF development side, Boflink will perform symbol resolution on imported symbols and rewrite them to match the BOF DFR format. BOF developers can use symbols imported from DLLs normally without needing to first prefix them with the library name they are imported from. Another feature is that it is capable of linking multiple COFFs together. These aspects help make the source code for BOFs more similar to the source code for traditional executables since the BOF specific artifacts are handled by Boflink.</p>
<p>On the BOF loader side, Boflink will create COFFs that are better optimized for BOF loaders to process rather than system linkers. Compilers will oftentimes include artifacts and structure things in ways that are more ideal for a linker to process rather than a loader. Some examples of this include COMDAT sections, relocation labels, grouped sections, COMMON symbols and linker metadata sections. Simplifying the COFFs loaded by a BOF loader can help reduce the risk of a BOF crashing since the loader will not need to include additional complexities for handling these cases.</p>
<h2 id="setup-and-usage">Setup and Usage</h2>
<p>Pre-built artifacts are provided on the releases page for download. These are built in CI and published for each release.</p>
<p>Setting up Boflink on Windows only requires the boflink executable. This executable can be placed in one of the <code>%PATH%</code> directories so that it is easier to run.</p>
<p>On Linux, Boflink is designed to integrate with the <a href="https://www.mingw-w64.org/" target="_blank" rel="noopener noreffer ">MinGW toolchain</a> and invoked via a compile driver. It is possible to use it with a custom toolchain; however, the MinGW one provided by many Linux distributions is the easiest to get started with.</p>
<p>A special symlink needs to be created for integrating Boflink with MinGW GCC. The reasoning for this is because GCC does not support using a custom linker directly. This symlink is used to get around that limitation. This workaround was used by the <a href="https://github.com/rui314/mold?tab=readme-ov-file#how-to-use" target="_blank" rel="noopener noreffer ">mold</a> linker when it did not have GCC support initially. A symlink needs to be created in an empty directory with the symlink name being <code>ld</code> and the target being the path to the installed boflink executable</p>
<p>The release archives include a small <code>install</code> script which will install the executable to <code>~/.local/bin/boflink</code> and create the symlink at <code>~/.local/libexec/boflink/ld</code>.</p>
<h3 id="install-from-source">Install From Source</h3>
<p>Installing from source requires <a href="https://www.rust-lang.org/tools/install" target="_blank" rel="noopener noreffer ">Rust</a> version &gt;=1.85. This can be checked by running <code>rustc --version</code> in a terminal window.</p>
<p>Building and installing from source requires downloading the source code and then running <code>cargo xtask install</code>.</p>
<p>The <code>cargo xtask ...</code> command is not any form of external plugin that needs to be installed but is an alias for cargo to build and run a small executable for installing the program correctly.</p>
<p>It will run <code>cargo install –path . –bin boflink</code> to build the executable from source and copy it into the <code>$CARGO_HOME/bin</code> path. On Linux, it also sets up the <code>ld</code> symlink for MinGW GCC by placing it in the <code>~/.local/libexec/boflink</code> directory.</p>
<p>The <code>cargo xtask uninstall</code> command can be used to undo everything from the install command. This only works as a means of uninstalling the program if it was installed using <code>cargo xtask install</code> and will not uninstall the executable if it was installed from a release archive.</p>
<h3 id="usage">Usage</h3>
<p>Boflink acts as a sort of “dumb linker”. This means that it does not include any form of default configuration and expects it to be provided from the command line or by other means.</p>
<h4 id="windows">Windows</h4>
<p>On Windows, Boflink should be used while inside a Visual Studio developer console. This environment includes a list of search paths that will be automatically included when searching for link libraries.</p>
<p>The boflink executable can be invoked directly in a Visual Studio developer console passing in any command line options.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-txt" data-lang="txt"><span class="line"><span class="cl">boflink [-o &lt;output&gt;] [options] &lt;files&gt;...
</span></span><span class="line"><span class="cl">boflink -o mybof.bof file1.obj file2.obj -lkernel32 -ladvapi32
</span></span></code></pre></div><h4 id="linux">Linux</h4>
<p>On Linux, the boflink executable is not meant to be invoked directly and instead should be used through a compile driver such as MinGW GCC or Clang. The compile driver will then invoke boflink passing in its default configuration for boflink to use.</p>
<p>For MinGW GCC, this requires the following command line flags.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-txt" data-lang="txt"><span class="line"><span class="cl">x86_64-w64-mingw32-gcc -B ~/.local/libexec/boflink -fno-lto -nostartfiles &lt;args&gt;...
</span></span><span class="line"><span class="cl">x86_64-w64-mingw32-gcc -B ~/.local/libexec/boflink -fno-lto -nostartfiles -o mybof.bof source.c object.o
</span></span></code></pre></div><p>The example above assumes that the <code>~/.local/libexec/boflink</code> directory has the <code>ld</code> symlink set up as mentioned in the setup section. The <code>-fno-lto</code> and <code>-nostartfiles</code> flags are also required for it to work properly.</p>
<p>Clang includes a <code>--ld-path=</code> flag for setting the linker. This needs to be the absolute path to the boflink executable.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-txt" data-lang="txt"><span class="line"><span class="cl">clang --ld-path=/path/to/boflink --target=x86_64-windows-gnu -nostartfiles &lt;args&gt;...
</span></span><span class="line"><span class="cl">clang --ld-path=/path/to/boflink --target=x86_64-windows-gnu -nostartfiles -o mybof.bof source.c object.o
</span></span></code></pre></div><p>The <code>--ld-path=</code> flag is very particular on its formatting and requires two hyphens for the flag prefix and an equal <code>=</code> sign. The <code>-nostartfiles</code> option is also required like with MinGW GCC to exclude startup files from the linker inputs.</p>
<h2 id="features">Features</h2>
<p>These are some of the currently implemented features of Boflink and how to use them.</p>
<h3 id="symbol-resolution">Symbol Resolution</h3>
<p>Boflink will resolve undefined symbols using the link libraries and library search paths specified on the command line. In the output BOF, the undefined symbols will have the resolved library names included in the symbol name to match the BOF DFR format.</p>
<p>For this example source file.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;windows.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;beacon.h&#34;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">go</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">DWORD</span> <span class="n">pid</span> <span class="o">=</span> <span class="nf">GetCurrentProcessId</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">    <span class="nf">BeaconPrintf</span><span class="p">(</span><span class="n">CALLBACK_OUTPUT</span><span class="p">,</span> <span class="s">&#34;pid: %lu</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">pid</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>Compiling it will cause the <code>GetCurrentProcessId</code> and <code>BeaconPrintf</code> symbols to show up as being undefined.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-txt" data-lang="txt"><span class="line"><span class="cl">matt@laptop ~&gt; ls
</span></span><span class="line"><span class="cl">beacon.h  example.c  Makefile
</span></span><span class="line"><span class="cl">matt@laptop ~&gt; make example.o
</span></span><span class="line"><span class="cl">x86_64-w64-mingw32-gcc    -c -o example.o example.c
</span></span><span class="line"><span class="cl">matt@laptop ~&gt; rabin2 -s example.o
</span></span><span class="line"><span class="cl">[Symbols]
</span></span><span class="line"><span class="cl">nth paddr      vaddr      bind   type size lib name                          demangled
</span></span><span class="line"><span class="cl">――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
</span></span><span class="line"><span class="cl">0   0x00000000 0x00000000 LOCAL  FILE 4        .file
</span></span><span class="line"><span class="cl">0   0x0000012c 0x00000000 GLOBAL FUNC 4        go
</span></span><span class="line"><span class="cl">0   0x0000012c 0x00000000 LOCAL  SECT 4        .text
</span></span><span class="line"><span class="cl">0   0x00000000 0x00000040 LOCAL  SECT 4        .data
</span></span><span class="line"><span class="cl">0   0x00000000 0x00000050 LOCAL  SECT 4        .bss
</span></span><span class="line"><span class="cl">0   0x0000016c 0x00000060 LOCAL  SECT 4        .rdata
</span></span><span class="line"><span class="cl">0   0x0000017c 0x00000070 LOCAL  SECT 4        .xdata
</span></span><span class="line"><span class="cl">0   0x00000188 0x00000080 LOCAL  SECT 4        .pdata
</span></span><span class="line"><span class="cl">0   0x00000194 0x00000090 LOCAL  UNK  4        .rdata$zzz
</span></span><span class="line"><span class="cl">0   ---------- ---------- NONE   UNK  4        imp.__imp_GetCurrentProcessId
</span></span><span class="line"><span class="cl">0   ---------- ---------- NONE   UNK  4        imp.__imp_BeaconPrintf
</span></span><span class="line"><span class="cl">matt@laptop ~&gt;
</span></span></code></pre></div><p>Passing the built <code>example.o</code> COFF through Boflink will result in Boflink resolving these symbols and rewriting them in the BOF DFR format with the name of the DLL that Boflink finds them defined in.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-txt" data-lang="txt"><span class="line"><span class="cl">matt@laptop ~&gt; ls
</span></span><span class="line"><span class="cl">beacon.h  example.c  example.o  Makefile
</span></span><span class="line"><span class="cl">matt@laptop ~&gt; x86_64-w64-mingw32-gcc -B ~/.local/libexec/boflink -fno-lto -nostartfiles -o example.bof example.o
</span></span><span class="line"><span class="cl">matt@laptop ~&gt; rabin2 -s example.bof
</span></span><span class="line"><span class="cl">[Symbols]
</span></span><span class="line"><span class="cl">nth paddr      vaddr      bind   type size lib name                                   demangled
</span></span><span class="line"><span class="cl">―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
</span></span><span class="line"><span class="cl">0   0x00000104 0x00000000 LOCAL  SECT 4        .text
</span></span><span class="line"><span class="cl">0   0x00000104 0x00000000 GLOBAL FUNC 4        go
</span></span><span class="line"><span class="cl">0   0x00000000 0x00000040 LOCAL  SECT 4        .data
</span></span><span class="line"><span class="cl">0   0x00000000 0x00000050 LOCAL  SECT 4        .bss
</span></span><span class="line"><span class="cl">0   0x00000144 0x00000060 LOCAL  SECT 4        .rdata
</span></span><span class="line"><span class="cl">0   0x00000194 0x000000b0 LOCAL  SECT 4        .xdata
</span></span><span class="line"><span class="cl">0   0x000001a0 0x000000c0 LOCAL  SECT 4        .pdata
</span></span><span class="line"><span class="cl">0   ---------- ---------- NONE   UNK  4        imp.__imp_BeaconPrintf
</span></span><span class="line"><span class="cl">0   ---------- ---------- NONE   UNK  4        imp.__imp_KERNEL32$GetCurrentProcessId
</span></span><span class="line"><span class="cl">matt@laptop ~&gt;
</span></span></code></pre></div><p>MinGW GCC includes kernel32 as a search library in its default configuration which is why it does not need to be included manually. In order to link against kernel32 on Windows using MSVC, Boflink needs to be run in a Visual Studio developer console with kernel32 passed as an additional link library on the command line.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-txt" data-lang="txt"><span class="line"><span class="cl"> matth@laptop ~&gt; ls
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        Directory: C:\Users\matth
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">Mode                LastWriteTime         Length Name
</span></span><span class="line"><span class="cl">----                -------------         ------ ----
</span></span><span class="line"><span class="cl">-a---         5/27/2025   1:50 PM          15962  beacon.h
</span></span><span class="line"><span class="cl">-a---         5/27/2025   1:50 PM            162  example.c
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"> matth@laptop ~&gt; cl /c /GS- .\example.c
</span></span><span class="line"><span class="cl">Microsoft (R) C/C++ Optimizing Compiler Version 19.44.35207.1 for x64
</span></span><span class="line"><span class="cl">Copyright (C) Microsoft Corporation.  All rights reserved.
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">example.c
</span></span><span class="line"><span class="cl"> matth@laptop ~&gt; ls
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        Directory: C:\Users\matth
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">Mode                LastWriteTime         Length Name
</span></span><span class="line"><span class="cl">----                -------------         ------ ----
</span></span><span class="line"><span class="cl">-a---         5/27/2025   1:50 PM          15962 beacon.h
</span></span><span class="line"><span class="cl">-a---         5/27/2025   1:50 PM            162 example.c
</span></span><span class="line"><span class="cl">-a---         5/27/2025   1:52 PM           1225 example.obj
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"> matth@laptop ~&gt; rabin2 -s .\example.obj
</span></span><span class="line"><span class="cl">[Symbols]
</span></span><span class="line"><span class="cl">nth paddr      vaddr      bind   type size lib name                          demangled
</span></span><span class="line"><span class="cl">--------------------------------------------------------------------------------------
</span></span><span class="line"><span class="cl">0   ---------- ---------- LOCAL  ABS  4        @comp.id-0x01048987
</span></span><span class="line"><span class="cl">0   ---------- ---------- LOCAL  ABS  4        @feat.00-0x80010090
</span></span><span class="line"><span class="cl">0   ---------- ---------- LOCAL  ABS  4        @vol.md-0x00000003
</span></span><span class="line"><span class="cl">0   0x0000012c 0x00000000 LOCAL  SECT 4        .drectve
</span></span><span class="line"><span class="cl">0   0x00000189 0x00000060 LOCAL  SECT 4        .debug$S
</span></span><span class="line"><span class="cl">0   0x00000219 0x000000f0 LOCAL  SECT 4        .text$mn
</span></span><span class="line"><span class="cl">0   ---------- ---------- NONE   UNK  4        imp.__imp_GetCurrentProcessId
</span></span><span class="line"><span class="cl">0   ---------- ---------- NONE   UNK  4        imp.__imp_BeaconPrintf
</span></span><span class="line"><span class="cl">0   0x00000219 0x000000f0 GLOBAL FUNC 4        go
</span></span><span class="line"><span class="cl">0   0x00000219 0x000000f0 LOCAL  6    4        $LN3
</span></span><span class="line"><span class="cl">0   0x0000025f 0x00000120 LOCAL  SECT 4        .xdata
</span></span><span class="line"><span class="cl">0   0x0000025f 0x00000120 LOCAL  UNK  4        $unwind$go
</span></span><span class="line"><span class="cl">0   0x00000267 0x00000130 LOCAL  SECT 4        .pdata
</span></span><span class="line"><span class="cl">0   0x00000267 0x00000130 LOCAL  UNK  4        $pdata$go
</span></span><span class="line"><span class="cl">0   0x00000291 0x00000140 LOCAL  SECT 4        .data
</span></span><span class="line"><span class="cl">0   0x00000291 0x00000140 LOCAL  UNK  4        $SG74138
</span></span><span class="line"><span class="cl">0   0x0000029b 0x00000150 LOCAL  SECT 4        .chks64
</span></span><span class="line"><span class="cl"> matth@laptop ~&gt; boflink -o example.bof .\example.obj -lkernel32
</span></span><span class="line"><span class="cl"> matth@laptop ~&gt; rabin2 -s .\example.bof
</span></span><span class="line"><span class="cl">[Symbols]
</span></span><span class="line"><span class="cl">nth paddr      vaddr      bind   type size lib name                                   demangled
</span></span><span class="line"><span class="cl">-----------------------------------------------------------------------------------------------
</span></span><span class="line"><span class="cl">0   0x000000b4 0x00000000 LOCAL  SECT 4        .text
</span></span><span class="line"><span class="cl">0   0x000000b4 0x00000000 GLOBAL FUNC 4        go
</span></span><span class="line"><span class="cl">0   0x000000dc 0x00000030 LOCAL  SECT 4        .xdata
</span></span><span class="line"><span class="cl">0   0x000000dc 0x00000030 LOCAL  UNK  4        $unwind$go
</span></span><span class="line"><span class="cl">0   0x000000e4 0x00000040 LOCAL  SECT 4        .pdata
</span></span><span class="line"><span class="cl">0   0x000000e4 0x00000040 LOCAL  UNK  4        $pdata$go
</span></span><span class="line"><span class="cl">0   0x000000f0 0x00000050 LOCAL  SECT 4        .data
</span></span><span class="line"><span class="cl">0   ---------- ---------- NONE   UNK  4        imp.__imp_BeaconPrintf
</span></span><span class="line"><span class="cl">0   ---------- ---------- NONE   UNK  4        imp.__imp_KERNEL32$GetCurrentProcessId
</span></span><span class="line"><span class="cl"> matth@laptop  ~&gt;
</span></span></code></pre></div><p>If any symbols could not be resolved, Boflink will return an error listing out what symbols were left undefined.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;windows.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;lmcons.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;beacon.h&#34;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">extern</span> <span class="kt">void</span> <span class="nf">UnresolvedSymbol</span><span class="p">(</span><span class="kt">void</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">void</span> <span class="nf">my_function</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nf">UnresolvedSymbol</span><span class="p">();</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">go</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nf">my_function</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="kt">char</span> <span class="n">username</span><span class="p">[</span><span class="n">UNLEN</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">0</span><span class="p">};</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="nf">GetUserNameA</span><span class="p">(</span><span class="n">username</span><span class="p">,</span> <span class="o">&amp;</span><span class="p">(</span><span class="n">DWORD</span><span class="p">){</span><span class="k">sizeof</span><span class="p">(</span><span class="n">username</span><span class="p">)})</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="nf">BeaconPrintf</span><span class="p">(</span><span class="n">CALLBACK_OUTPUT</span><span class="p">,</span> <span class="s">&#34;Your username is %s&#34;</span><span class="p">,</span> <span class="n">username</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-txt" data-lang="txt"><span class="line"><span class="cl"> matth@laptop ~&gt; cl /c /GS- .\example.c
</span></span><span class="line"><span class="cl">Microsoft (R) C/C++ Optimizing Compiler Version 19.44.35207.1 for x64
</span></span><span class="line"><span class="cl">Copyright (C) Microsoft Corporation.  All rights reserved.
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">example.c
</span></span><span class="line"><span class="cl"> matth@laptop ~&gt; boflink -o example.bof .\example.obj -lkernel32
</span></span><span class="line"><span class="cl">boflink: error: undefined symbol: __declspec(dllimport) GetUserNameA
</span></span><span class="line"><span class="cl">&gt;&gt;&gt; referenced by .\example.obj:(go)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">boflink: error: undefined symbol: UnresolvedSymbol
</span></span><span class="line"><span class="cl">&gt;&gt;&gt; referenced by .\example.obj:(my_function)
</span></span><span class="line"><span class="cl"> matth@laptop ~ [1]&gt;
</span></span></code></pre></div><h3 id="linking-multiple-files">Linking Multiple Files</h3>
<p>Boflink is also capable of linking multiple object files together into a single BOF. This is commonly referred to as “partial linking” where multiple object files are combined to produce a single object file rather than a full executable or shared library.</p>
<p>go.c</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;beacon.h&#34;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;other.h&#34;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">go</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nf">BeaconPrintf</span><span class="p">(</span><span class="n">CALLBACK_OUTPUT</span><span class="p">,</span> <span class="s">&#34;Hello world from the go() function&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="nf">other_function</span><span class="p">();</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>other.h</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#ifndef OTHER_H
</span></span></span><span class="line"><span class="cl"><span class="cp">#define OTHER_H
</span></span></span><span class="line"><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">other_function</span><span class="p">(</span><span class="kt">void</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="cp">#endif </span><span class="c1">// OTHER_H
</span></span></span></code></pre></div><p>other.c</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;other.h&#34;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;beacon.h&#34;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">other_function</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nf">BeaconPrintf</span><span class="p">(</span><span class="n">CALLBACK_OUTPUT</span><span class="p">,</span> <span class="s">&#34;Hello world from other_function()&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>Using MinGW GCC</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-txt" data-lang="txt"><span class="line"><span class="cl">matt@laptop ~&gt; ls
</span></span><span class="line"><span class="cl">beacon.h  go.c  Makefile  other.c  other.h
</span></span><span class="line"><span class="cl">matt@laptop ~&gt; x86_64-w64-mingw32-gcc -B ~/.local/libexec/boflink -fno-lto -nostartfiles -o mybof.bof go.c other.c
</span></span><span class="line"><span class="cl">matt@laptop ~&gt; ls
</span></span><span class="line"><span class="cl">beacon.h  go.c  Makefile  mybof.bof  other.c  other.h
</span></span><span class="line"><span class="cl">matt@laptop ~&gt; rabin2 -s mybof.bof
</span></span><span class="line"><span class="cl">[Symbols]
</span></span><span class="line"><span class="cl">nth paddr      vaddr      bind   type size lib name                                   demangled
</span></span><span class="line"><span class="cl">―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
</span></span><span class="line"><span class="cl">0   0x00000104 0x00000000 LOCAL  SECT 4        .text
</span></span><span class="line"><span class="cl">0   0x00000104 0x00000000 GLOBAL FUNC 4        go
</span></span><span class="line"><span class="cl">0   0x00000134 0x00000030 GLOBAL FUNC 4        other_function
</span></span><span class="line"><span class="cl">0   0x00000000 0x00000090 LOCAL  SECT 4        .data
</span></span><span class="line"><span class="cl">0   0x00000000 0x000000a0 LOCAL  SECT 4        .bss
</span></span><span class="line"><span class="cl">0   0x00000194 0x000000b0 LOCAL  SECT 4        .rdata
</span></span><span class="line"><span class="cl">0   0x00000244 0x00000160 LOCAL  SECT 4        .xdata
</span></span><span class="line"><span class="cl">0   0x0000025c 0x00000180 LOCAL  SECT 4        .pdata
</span></span><span class="line"><span class="cl">0   ---------- ---------- NONE   UNK  4        imp.__imp_BeaconPrintf
</span></span><span class="line"><span class="cl">0   ---------- ---------- NONE   UNK  4        imp.__imp_KERNEL32$GetCurrentProcessId
</span></span><span class="line"><span class="cl">matt@laptop ~&gt;
</span></span></code></pre></div><p>Using MSVC on Windows</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-txt" data-lang="txt"><span class="line"><span class="cl">matth@laptop ~&gt; ls
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        Directory: C:\Users\matth
</span></span><span class="line"><span class="cl"> 
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">Mode                LastWriteTime         Length Name
</span></span><span class="line"><span class="cl">----                -------------         ------ ----
</span></span><span class="line"><span class="cl">-a---         5/27/2025   1:50 PM          15962 beacon.h
</span></span><span class="line"><span class="cl">-a---         5/27/2025   2:33 PM            164 go.c
</span></span><span class="line"><span class="cl">-a---         5/27/2025   2:33 PM            273 other.c
</span></span><span class="line"><span class="cl">-a---         5/27/2025   2:33 PM             85 other.h
</span></span><span class="line"><span class="cl"> 
</span></span><span class="line"><span class="cl"> matth@laptop ~&gt; cl /c /GS- .\go.c .\other.c
</span></span><span class="line"><span class="cl">Microsoft (R) C/C++ Optimizing Compiler Version 19.44.35207.1 for x64
</span></span><span class="line"><span class="cl">Copyright (C) Microsoft Corporation.  All rights reserved.
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">go.c
</span></span><span class="line"><span class="cl">other.c
</span></span><span class="line"><span class="cl">Generating Code...
</span></span><span class="line"><span class="cl"> matth@laptop ~&gt; ls
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        Directory: C:\Users\matth
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">Mode                LastWriteTime         Length Name
</span></span><span class="line"><span class="cl">----                -------------         ------ ----
</span></span><span class="line"><span class="cl">-a---         5/27/2025   1:50 PM          15962 beacon.h
</span></span><span class="line"><span class="cl">-a---         5/27/2025   2:33 PM            164 go.c
</span></span><span class="line"><span class="cl">-a---         5/27/2025   2:35 PM           1225 go.obj
</span></span><span class="line"><span class="cl">-a---         5/27/2025   2:33 PM            273 other.c
</span></span><span class="line"><span class="cl">-a---         5/27/2025   2:33 PM             85 other.h
</span></span><span class="line"><span class="cl">-a---         5/27/2025   2:35 PM           1364 other.obj
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"> matth@laptop ~&gt; boflink -o mybof.bof .\go.obj .\other.obj -lkernel32
</span></span><span class="line"><span class="cl"> matth@laptop ~&gt; ls
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        Directory: C:\Users\matth
</span></span><span class="line"><span class="cl"> 
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">Mode                LastWriteTime         Length Name
</span></span><span class="line"><span class="cl">----                -------------         ------ ----
</span></span><span class="line"><span class="cl">-a---         5/27/2025   1:50 PM          15962 beacon.h
</span></span><span class="line"><span class="cl">-a---         5/27/2025   2:33 PM            164 go.c
</span></span><span class="line"><span class="cl">-a---         5/27/2025   2:35 PM           1225 go.obj
</span></span><span class="line"><span class="cl">-a---         5/27/2025   2:35 PM            947 mybof.bof
</span></span><span class="line"><span class="cl">-a---         5/27/2025   2:33 PM            273 other.c
</span></span><span class="line"><span class="cl">-a---         5/27/2025   2:33 PM             85 other.h
</span></span><span class="line"><span class="cl">-a---         5/27/2025   2:35 PM           1364 other.obj
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"> matth@laptop ~&gt; rabin2 -s .\mybof.bof
</span></span><span class="line"><span class="cl">[Symbols]
</span></span><span class="line"><span class="cl">nth paddr      vaddr      bind   type size lib name                                   demangled
</span></span><span class="line"><span class="cl">-----------------------------------------------------------------------------------------------
</span></span><span class="line"><span class="cl">0   0x000000b4 0x00000000 LOCAL  SECT 4        .text
</span></span><span class="line"><span class="cl">0   0x000000b4 0x00000000 GLOBAL FUNC 4        go
</span></span><span class="line"><span class="cl">0   0x000000d4 0x00000020 GLOBAL FUNC 4        other_function
</span></span><span class="line"><span class="cl">0   0x0000010c 0x00000060 LOCAL  SECT 4        .xdata
</span></span><span class="line"><span class="cl">0   0x0000010c 0x00000060 LOCAL  UNK  4        $unwind$go
</span></span><span class="line"><span class="cl">0   0x00000114 0x00000068 LOCAL  UNK  4        $unwind$other_function
</span></span><span class="line"><span class="cl">0   0x0000011c 0x00000070 LOCAL  SECT 4        .pdata
</span></span><span class="line"><span class="cl">0   0x0000011c 0x00000070 LOCAL  UNK  4        $pdata$go
</span></span><span class="line"><span class="cl">0   0x00000128 0x0000007c LOCAL  UNK  4        $pdata$other_function
</span></span><span class="line"><span class="cl">0   0x00000134 0x00000090 LOCAL  SECT 4        .data
</span></span><span class="line"><span class="cl">0   ---------- ---------- NONE   UNK  4        imp.__imp_BeaconPrintf
</span></span><span class="line"><span class="cl">0   ---------- ---------- NONE   UNK  4        imp.__imp_KERNEL32$GetCurrentProcessId
</span></span><span class="line"><span class="cl"> matth@laptop ~&gt;
</span></span></code></pre></div><p>Partial linking is a feature also supported in GNU ld. The difference between partial linking in Boflink and GNU ld is that GNU ld’s partial linking is mainly for doing incremental linking in a larger build process.</p>
<p>Incremental linking is an optimization feature used to help speed up rebuilds for a program. This works by linking multiple object files together to produce a new “pre-linked” object file for the final linking stage.</p>
<p>It is pretty common for linkers to embed additional metadata in the “pre-linked” object file during incremental linking to help speed up the final linking process.</p>
<p>Here is an example of using MinGW ld to perform partial linking with the files above.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-txt" data-lang="txt"><span class="line"><span class="cl">matt@laptop ~&gt; x86_64-w64-mingw32-gcc -r -o combined.o go.c other.c
</span></span><span class="line"><span class="cl">matt@laptop ~&gt; ls
</span></span><span class="line"><span class="cl">beacon.h  combined.o  go.c  Makefile  other.c  other.h
</span></span><span class="line"><span class="cl">matt@laptop ~&gt; rabin2 -s combined.o
</span></span><span class="line"><span class="cl">[Symbols]
</span></span><span class="line"><span class="cl">nth paddr      vaddr      bind   type size lib name                          demangled
</span></span><span class="line"><span class="cl">――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
</span></span><span class="line"><span class="cl">0   0x00000000 0x00000000 LOCAL  FILE 4        .file
</span></span><span class="line"><span class="cl">0   0x0000012c 0x00000000 GLOBAL FUNC 4        go
</span></span><span class="line"><span class="cl">0   0x0000012c 0x00000000 LOCAL  SECT 4        .text
</span></span><span class="line"><span class="cl">0   0x00000000 0x00000090 LOCAL  SECT 4        .data
</span></span><span class="line"><span class="cl">0   0x00000000 0x000001d0 LOCAL  SECT 4        .bss
</span></span><span class="line"><span class="cl">0   0x000001bc 0x000000a0 LOCAL  SECT 4        .rdata
</span></span><span class="line"><span class="cl">0   0x000002c4 0x000001b0 LOCAL  SECT 4        .xdata
</span></span><span class="line"><span class="cl">0   0x000002ac 0x00000190 LOCAL  SECT 4        .pdata
</span></span><span class="line"><span class="cl">0   0x0000026c 0x00000150 LOCAL  UNK  4        .rdata$zzz
</span></span><span class="line"><span class="cl">0   0x00000000 0x00000000 LOCAL  FILE 4        .file
</span></span><span class="line"><span class="cl">0   0x0000015c 0x00000030 GLOBAL FUNC 4        other_function
</span></span><span class="line"><span class="cl">0   0x0000015c 0x00000030 LOCAL  SECT 4        .text
</span></span><span class="line"><span class="cl">0   0x00000000 0x00000090 LOCAL  SECT 4        .data
</span></span><span class="line"><span class="cl">0   0x00000000 0x000001d0 LOCAL  SECT 4        .bss
</span></span><span class="line"><span class="cl">0   0x000001ec 0x000000d0 LOCAL  SECT 4        .rdata
</span></span><span class="line"><span class="cl">0   0x000002d0 0x000001bc LOCAL  SECT 4        .xdata
</span></span><span class="line"><span class="cl">0   0x000002b8 0x0000019c LOCAL  SECT 4        .pdata
</span></span><span class="line"><span class="cl">0   0x0000022c 0x00000110 LOCAL  UNK  4        .rdata$zzz
</span></span><span class="line"><span class="cl">0   ---------- ---------- NONE   UNK  4        imp.__imp_GetCurrentProcessId
</span></span><span class="line"><span class="cl">0   ---------- ---------- NONE   UNK  4        imp._pei386_runtime_relocator
</span></span><span class="line"><span class="cl">0   ---------- ---------- NONE   UNK  4        imp.__imp_BeaconPrintf
</span></span><span class="line"><span class="cl">matt@laptop ~&gt;
</span></span></code></pre></div><p>You can see above that MinGW ld does not deduplicate the section symbols. It will also embed the undefined <code>_pei386_runttime_relocator</code> symbol because it knows that it will need it later on in the final linking process. This is helpful for further linking together a full program but can cause issues in a BOF loader.</p>
<p>Boflink’s partial linking process includes various linker passes specifically designed for tailoring the COFF for a loader to process. This includes: deduplicating section symbols, discarding linker metadata sections, merging grouped sections, applying relocations to same-section defined symbols, allocating space for COMMON symbols, handling COMDAT sections and some others. The result of this is that the final output COFF is much simpler than what MinGW ld produces which makes it easier for BOF loaders to load.</p>
<h3 id="comment-pragma-link-libraries">Comment Pragma Link Libraries</h3>
<p>When using MSVC toolchains, it is common for them to embed additional metadata inside the compiled COFF for the linker to process. These are known as <a href="https://learn.microsoft.com/en-us/cpp/preprocessor/comment-c-cpp" target="_blank" rel="noopener noreffer ">comment records</a> and are added using the <code>#pragma comment</code> preprocessor directive. Some of these comment records include additional options for the linker to process.</p>
<p>Boflink currently supports processing <a href="https://learn.microsoft.com/en-us/cpp/preprocessor/comment-c-cpp?view=msvc-170#lib" target="_blank" rel="noopener noreffer ">lib</a> records for including additional search libraries when resolving symbols.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;windows.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;lmcons.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;beacon.h&#34;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="cp">#pragma comment(lib, &#34;kernel32&#34;)
</span></span></span><span class="line"><span class="cl"><span class="cp">#pragma comment(lib, &#34;advapi32&#34;)
</span></span></span><span class="line"><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">go</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">DWORD</span> <span class="n">pid</span> <span class="o">=</span> <span class="nf">GetCurrentProcessId</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">    <span class="nf">BeaconPrintf</span><span class="p">(</span><span class="n">CALLBACK_OUTPUT</span><span class="p">,</span> <span class="s">&#34;Current process id is %lu&#34;</span><span class="p">,</span> <span class="n">pid</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="kt">char</span> <span class="n">username</span><span class="p">[</span><span class="n">UNLEN</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">0</span><span class="p">};</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="nf">GetUserNameA</span><span class="p">(</span><span class="n">username</span><span class="p">,</span> <span class="o">&amp;</span><span class="p">(</span><span class="n">DWORD</span><span class="p">){</span><span class="k">sizeof</span><span class="p">(</span><span class="n">username</span><span class="p">)})</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="nf">BeaconPrintf</span><span class="p">(</span><span class="n">CALLBACK_OUTPUT</span><span class="p">,</span> <span class="s">&#34;Your username is %s&#34;</span><span class="p">,</span> <span class="n">username</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>When processing this file, Boflink will see the “kernel32” and “advapi32” link libraries and include them in the symbol resolution phase.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-txt" data-lang="txt"><span class="line"><span class="cl">matth@laptop ~&gt; ls
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        Directory: C:\Users\matth
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">Mode                LastWriteTime         Length Name
</span></span><span class="line"><span class="cl">----                -------------         ------ ----
</span></span><span class="line"><span class="cl">-a---         5/27/2025   1:50 PM          15962 beacon.h
</span></span><span class="line"><span class="cl">-a---         5/27/2025   3:33 PM            457 example.c
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"> matth@laptop ~&gt; cl /c /GS- .\example.c
</span></span><span class="line"><span class="cl">Microsoft (R) C/C++ Optimizing Compiler Version 19.44.35207.1 for x64
</span></span><span class="line"><span class="cl">Copyright (C) Microsoft Corporation.  All rights reserved.
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">example.c
</span></span><span class="line"><span class="cl"> matth@laptop ~&gt; ls
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        Directory: C:\Users\matth
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">Mode                LastWriteTime         Length Name
</span></span><span class="line"><span class="cl">----                -------------         ------ ----
</span></span><span class="line"><span class="cl">-a---         5/27/2025   1:50 PM          15962 beacon.h
</span></span><span class="line"><span class="cl">-a---         5/27/2025   3:33 PM            457 example.c
</span></span><span class="line"><span class="cl">-a---         5/27/2025   3:36 PM           1476 example.obj
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"> matth@laptop ~&gt; boflink -o example.bof .\example.obj
</span></span><span class="line"><span class="cl"> matth@laptop ~&gt; rabin2 -s .\example.bof
</span></span><span class="line"><span class="cl">[Symbols]
</span></span><span class="line"><span class="cl">nth paddr      vaddr      bind   type size lib name                                   demangled
</span></span><span class="line"><span class="cl">-----------------------------------------------------------------------------------------------
</span></span><span class="line"><span class="cl">0   0x000000b4 0x00000000 LOCAL  SECT 4        .text
</span></span><span class="line"><span class="cl">0   0x000000b4 0x00000000 GLOBAL FUNC 4        go
</span></span><span class="line"><span class="cl">0   0x00000128 0x00000080 LOCAL  SECT 4        .xdata
</span></span><span class="line"><span class="cl">0   0x00000128 0x00000080 LOCAL  UNK  4        $unwind$go
</span></span><span class="line"><span class="cl">0   0x00000134 0x00000090 LOCAL  SECT 4        .pdata
</span></span><span class="line"><span class="cl">0   0x00000134 0x00000090 LOCAL  UNK  4        $pdata$go
</span></span><span class="line"><span class="cl">0   0x00000140 0x000000a0 LOCAL  SECT 4        .data
</span></span><span class="line"><span class="cl">0   ---------- ---------- NONE   UNK  4        imp.__imp_BeaconPrintf
</span></span><span class="line"><span class="cl">0   ---------- ---------- NONE   UNK  4        imp.__imp_KERNEL32$GetCurrentProcessId
</span></span><span class="line"><span class="cl">0   ---------- ---------- NONE   UNK  4        imp.__imp_ADVAPI32$GetUserNameA
</span></span><span class="line"><span class="cl"> matth@laptop ~&gt;
</span></span></code></pre></div><p>Note that this method of passing link libraries to Boflink depends on if the compiler used to compile the source files supports embedding comment records.</p>
<h3 id="bss-handling">BSS Handling</h3>
<p>A common limitation with many BOF loaders is that they do not support loading the .bss section. Boflink includes a <code>--merge-bss</code> flag to add .bss compatibility for BOF loaders that do not support it. This will zero-initialize .bss defined symbols and place them at the end of the .data section. It effectively does what many BOF developers will do in their code where they default initialize global variables or use attributes to have the compiler define them in the .data section. It does not “magically fix” the .bss section for BOF loaders but instead offloads the task of zero-initializing them to Boflink.</p>
<p>I am curious what the reasonings are for many BOF loaders not adding support for loading the .bss section. From the BOF loader perspective, an uninitialized data section and a file-backed section are loaded very similarly. The only difference is that the uninitialized data section will set the <code>IMAGE_SCN_CNT_UNINITIALIZED_DATA</code> flag in the section header characteristics to indicate that the section is not file-backed. If this flag is present, the loader does not initialize the section with data from the file but instead zero-initializes it. The size needed for the allocated section is stored in the <code>SizeOfRawData</code> field like with regular file-backed sections. Adding support for the .bss section in a BOF loader involves checking for that flag in the section header and either zero-initializing the allocated section or initializing it with the data found at the <code>PointerToRawData</code> file offset in the header.</p>
<p><a href="https://github.com/trustedsec/COFFLoader/blob/6f366f09ee4d32af960922c9481f53eb97952014/COFFLoader.c#L304" target="_blank" rel="noopener noreffer ">TrustedSec’s COFFLoader</a> will zero-initialize any sections which have a non-zero size and a <code>PointerToRawData</code> field set to <code>NULL</code>. This means that it does have support for loading the .bss section since the .bss section&rsquo;s <code>PointerToRawData</code> field will be set to <code>NULL</code> and the <code>SizeOfRawData</code> field will be non-zero.</p>
<p>bsstest.c</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;windows.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;beacon.h&#34;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">int</span> <span class="n">bss_variable</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">float</span> <span class="n">other_bss_variable</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">go</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">bss_variable</span> <span class="o">=</span> <span class="mi">123</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="nf">BeaconPrintf</span><span class="p">(</span><span class="n">CALLBACK_OUTPUT</span><span class="p">,</span> <span class="s">&#34;bss_variable: %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">bss_variable</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">other_bss_variable</span> <span class="o">=</span> <span class="mf">3.14</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="nf">BeaconPrintf</span><span class="p">(</span><span class="n">CALLBACK_OUTPUT</span><span class="p">,</span> <span class="s">&#34;other_bss_variable: %0.2f</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">other_bss_variable</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-txt" data-lang="txt"><span class="line"><span class="cl">matt@laptop ~/COFFLoader (main)&gt; x86_64-w64-mingw32-gcc -c -o bsstest.o bsstest.c
</span></span><span class="line"><span class="cl">matt@laptop ~/COFFLoader (main)&gt; ./COFFLoader64.exe go bsstest.o
</span></span><span class="line"><span class="cl">Got contents of COFF file
</span></span><span class="line"><span class="cl">Running/Parsing the COFF file
</span></span><span class="line"><span class="cl">bss_variable: 123
</span></span><span class="line"><span class="cl">other_bss_variable: 3.14
</span></span><span class="line"><span class="cl">Ran/parsed the coff
</span></span><span class="line"><span class="cl">Outdata Below:
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">bss_variable: 123
</span></span><span class="line"><span class="cl">other_bss_variable: 3.14
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">matt@laptop ~/COFFLoader (main)&gt;
</span></span></code></pre></div><p>What may cause confusion with the .bss section are the differences between .bss defined symbols and COMMON symbols. MaskRay’s blog post “<a href="https://maskray.me/blog/2022-02-06-all-about-common-symbols" target="_blank" rel="noopener noreffer ">All about COMMON symbols</a>“ does a great job explaining them and why they can cause many issues in C.</p>
<p><a href="https://gcc.gnu.org/gcc-10/changes.html#c" target="_blank" rel="noopener noreffer ">GCC 10</a> and <a href="https://releases.llvm.org/11.0.0/tools/clang/docs/ReleaseNotes.html#modified-compiler-flags" target="_blank" rel="noopener noreffer ">Clang 11</a> (released around 2020) included a change where the <code>-fno-common</code> flag is now added by default during compilation. This will cause public uninitialized global variables to be treated as .bss defined symbols rather than COMMON symbols.</p>
<p>Here is an example of what COMMON symbols look like and how they differ from .bss defined symbols.</p>
<p>commonstest.c</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;windows.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;beacon.h&#34;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="n">common_symbol</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">int</span> <span class="n">bss_symbol</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">go</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">common_symbol</span> <span class="o">=</span> <span class="mi">123</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="nf">BeaconPrintf</span><span class="p">(</span><span class="n">CALLBACK_OUTPUT</span><span class="p">,</span> <span class="s">&#34;common_symbol: %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">common_symbol</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">bss_symbol</span> <span class="o">=</span> <span class="mi">123</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="nf">BeaconPrintf</span><span class="p">(</span><span class="n">CALLBACK_OUTPUT</span><span class="p">,</span> <span class="s">&#34;bss_symbol: %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">bss_symbol</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>The <code>common_symbol</code> is a public uninitialized global variable. This is what causes COMMON symbols to appear in a compiled object file.</p>
<p>The <code>-fcommon</code> compile flag is needed when using MinGW GCC to treat <code>common_symbol</code> as a COMMON symbol since the <code>-fno-common</code> flag is included by default. The <code>bss_symbol</code> variable is a regular .bss defined symbol since it was declared with <code>static</code> storage duration. These symbols can be viewed in the COFF symbol table using <code>llvm-readobj</code>.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-txt" data-lang="txt"><span class="line"><span class="cl">matt@laptop ~&gt; ls
</span></span><span class="line"><span class="cl">beacon.h  commonstest.c
</span></span><span class="line"><span class="cl">matt@laptop ~&gt; x86_64-w64-mingw32-gcc -fcommon -c -o commonstest.o commonstest.c
</span></span><span class="line"><span class="cl">matt@laptop ~&gt; llvm-readobj -s commonstest.o
</span></span><span class="line"><span class="cl">…
</span></span><span class="line"><span class="cl"> Symbol {
</span></span><span class="line"><span class="cl">    Name: bss_symbol
</span></span><span class="line"><span class="cl">    Value: 0
</span></span><span class="line"><span class="cl">    Section: .bss (3)
</span></span><span class="line"><span class="cl">    BaseType: Null (0x0)
</span></span><span class="line"><span class="cl">    ComplexType: Null (0x0)
</span></span><span class="line"><span class="cl">    StorageClass: Static (0x3)
</span></span><span class="line"><span class="cl">    AuxSymbolCount: 0
</span></span><span class="line"><span class="cl">  }
</span></span><span class="line"><span class="cl">…
</span></span><span class="line"><span class="cl">  Symbol {
</span></span><span class="line"><span class="cl">    Name: common_symbol
</span></span><span class="line"><span class="cl">    Value: 4
</span></span><span class="line"><span class="cl">    Section: IMAGE_SYM_UNDEFINED (0)
</span></span><span class="line"><span class="cl">    BaseType: Null (0x0)
</span></span><span class="line"><span class="cl">    ComplexType: Null (0x0)
</span></span><span class="line"><span class="cl">    StorageClass: External (0x2)
</span></span><span class="line"><span class="cl">    AuxSymbolCount: 0
</span></span><span class="line"><span class="cl">  }
</span></span><span class="line"><span class="cl">…
</span></span></code></pre></div><p>The <code>bss_symbol</code> shows up as being defined in the .bss section at address 0. The <code>common_symbol</code> is rather different. COMMON symbols in COFFs are represented as having a section number of <code>IMAGE_SYM_UNDEFINED</code> and a <code>Value</code> that is non-zero. This is very similar to regular undefined symbols but with the only difference being that the <code>Value</code> field is non-zero for COMMONS. The system linker will handle resolving COMMON symbols as outlined in MaskRay&rsquo;s blog post mentioned above but they ultimately will not end up defined in the .bss section until after linking.</p>
<p>MSVC&rsquo;s defaults are different than MinGW GCC or Clang and will compile public uninitialized global variables as COMMON symbols. This is equivalent to passing the <code>-fcommon</code> flag like in the example above.</p>
<p>One way to avoid COMMON symbols when using MSVC is by making uninitialized global variables <code>static</code>. The drawback with this is that the symbol will be local to the translation unit it is being compiled in and cannot be referenced externally.</p>
<p>As far as I have discovered, the only way to create a public .bss defined symbol with MSVC is by wrapping it in a <a href="https://learn.microsoft.com/en-us/cpp/preprocessor/bss-seg?view=msvc-170" target="_blank" rel="noopener noreffer ">bss_seg pragma</a>.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;windows.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;beacon.h&#34;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="cp">#pragma bss_seg(push, bss, &#34;.bss&#34;)
</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="n">bss_symbol</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="cp">#pragma bss_seg(pop, bss)
</span></span></span><span class="line"><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">go</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">bss_symbol</span> <span class="o">=</span> <span class="mi">123</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="nf">BeaconPrintf</span><span class="p">(</span><span class="n">CALLBACK_OUTPUT</span><span class="p">,</span> <span class="s">&#34;bss_symbol: %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">bss_symbol</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>I can see why the confusion around COMMON symbols is the reason why BOF loaders decided to not support BOFs with uninitialized global variables. MinGW GCC and Clang changed their defaults for them after the initial BOF loaders were released which would cause COMMON symbols to show up more frequently during testing.</p>
<p>There is not a lot of easily accessible information online explaining COMMON symbols in-depth which makes them rather obscure. Many <a href="https://www.geeksforgeeks.org/memory-layout-of-c-program/" target="_blank" rel="noopener noreffer ">C development courses</a> do not mention them at all because they are a compiler-specific &ldquo;feature&rdquo; not really part of the language itself. There are many pitfalls when using COMMON symbols in C and exist mainly for FORTRAN compatibility.</p>
<p>BOF loaders should be able to support .bss defined symbols fairly easily. As stated above, TrustedSec’s COFFLoader does support them. I personally do not expect BOF loaders to handle COMMON symbols due to the complexity but they can be avoided pretty easily in the BOF source code.</p>
<p>Boflink does support handling COMMON symbols like a regular linker does and will allocate them at the end of the .bss section if they do appear.</p>
<h3 id="custom-beacon-api">Custom Beacon API</h3>
<p>Beacon Object Files can utilize what is known as a “Beacon API” or a set of API functions the BOF loader exposes for the BOF to interact with the loader itself.</p>
<p>Cobalt Strike’s Beacon API is included by default but developers can utilize a custom Beacon API instead of the default Cobalt Strike one.</p>
<p>The custom Beacon API is an import library that is passed in using the <code>--custom-api</code> command line flag.</p>
<p>Here is an example on how to use a custom Beacon API with Boflink.</p>
<p>The custom API for this example includes four functions: <code>MyApiVersion</code>, <code>MyApiPrintf</code>, <code>MyApiAlloc</code> and <code>MyApiFree</code>. A <a href="https://learn.microsoft.com/en-us/cpp/build/reference/module-definition-dot-def-files" target="_blank" rel="noopener noreffer ">Module-Definition File</a> can be used for creating an import library that exports these symbols.</p>
<p>myapi.def</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-txt" data-lang="txt"><span class="line"><span class="cl">LIBRARY MyApi
</span></span><span class="line"><span class="cl">EXPORTS
</span></span><span class="line"><span class="cl">  MyApiVersion
</span></span><span class="line"><span class="cl">  MyApiPrintf
</span></span><span class="line"><span class="cl">  MyApiAlloc
</span></span><span class="line"><span class="cl">  MyApiFree
</span></span></code></pre></div><p>Using <code>llvm-dlltool</code> on Linux</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-txt" data-lang="txt"><span class="line"><span class="cl">llvm-dlltool -l libmyapi.a -d myapi.def
</span></span></code></pre></div><p>Using <code>lib.exe</code> on Windows</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-txt" data-lang="txt"><span class="line"><span class="cl">lib /machine:x64 /def:myapi.def /out:myapi.lib
</span></span></code></pre></div><p>Using MinGW dlltool</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-txt" data-lang="txt"><span class="line"><span class="cl">x86_64-w64-mingw32-dlltool -l libmyapi.a -d myapi.def
</span></span></code></pre></div><p>It is recommended to use <code>llvm-dlltool</code> over MinGW dlltool. The reason for this is that the import libraries that <code>llvm-dlltool</code> and <code>lib.exe</code> create are better optimized when compared to MinGW dlltool.</p>
<p>Here is the example source code.</p>
<p>myapi.h</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#ifndef MYAPI_H
</span></span></span><span class="line"><span class="cl"><span class="cp">#define MYAPI_H
</span></span></span><span class="line"><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="cl"><span class="cp">#ifdef __cplusplus
</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="k">extern</span> <span class="s">&#34;C&#34;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"><span class="cp">#endif </span><span class="c1">// __cplusplus
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdint.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="cl"><span class="kr">__declspec</span><span class="p">(</span><span class="n">dllimport</span><span class="p">)</span> <span class="kt">int</span> <span class="nf">MyApiVersion</span><span class="p">(</span><span class="kt">void</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="kr">__declspec</span><span class="p">(</span><span class="n">dllimport</span><span class="p">)</span> <span class="kt">void</span> <span class="nf">MyApiPrintf</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">format</span><span class="p">,</span> <span class="p">...);</span>
</span></span><span class="line"><span class="cl"><span class="kr">__declspec</span><span class="p">(</span><span class="n">dllimport</span><span class="p">)</span> <span class="kt">void</span> <span class="o">*</span><span class="nf">MyApiAlloc</span><span class="p">(</span><span class="kt">size_t</span> <span class="n">size</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="kr">__declspec</span><span class="p">(</span><span class="n">dllimport</span><span class="p">)</span> <span class="kt">void</span> <span class="nf">MyApiFree</span><span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="n">ptr</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="cp">#ifdef __cplusplus
</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="p">};</span>
</span></span><span class="line"><span class="cl"><span class="cp">#endif </span><span class="c1">// __cplusplus
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>
</span></span><span class="line"><span class="cl"><span class="cp">#endif </span><span class="c1">// MYAPI_H
</span></span></span></code></pre></div><p>custom-api.c</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;myapi.h&#34;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">go</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="kt">int</span> <span class="n">version</span> <span class="o">=</span> <span class="nf">MyApiVersion</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">    <span class="nf">MyApiPrintf</span><span class="p">(</span><span class="s">&#34;MyApiVersion: %d&#34;</span><span class="p">,</span> <span class="n">version</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="kt">int</span> <span class="o">*</span><span class="n">value</span> <span class="o">=</span> <span class="nf">MyApiAlloc</span><span class="p">(</span><span class="k">sizeof</span><span class="p">(</span><span class="kt">int</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">    <span class="o">*</span><span class="n">value</span> <span class="o">=</span> <span class="mi">123</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="nf">MyApiPrintf</span><span class="p">(</span><span class="s">&#34;value: %d&#34;</span><span class="p">,</span> <span class="o">*</span><span class="n">value</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="nf">MyApiFree</span><span class="p">(</span><span class="n">value</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>The BOF can be compiled and linked with the import library that contains the API symbols.</p>
<p>MinGW GCC</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-txt" data-lang="txt"><span class="line"><span class="cl"># llvm-dlltool is preferred over x86_64-w64-mingw32-dlltool
</span></span><span class="line"><span class="cl">llvm-dlltool -l libmyapi.a -d myapi.def
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"># x86_64-w64-mingw32-dlltool is supported but should be used only if llvm-dlltool is not available
</span></span><span class="line"><span class="cl">x86_64-w64-mingw32-dlltool -l libmyapi.a -d myapi.def
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"># Usage
</span></span><span class="line"><span class="cl">x86_64-w64-mingw32-gcc -B ~/.local/libexec/boflink -fno-lto -nostartfiles -Wl,--custom-api=libmyapi.a -o custom-api.bof custom-api.c
</span></span></code></pre></div><p>Clang</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-txt" data-lang="txt"><span class="line"><span class="cl">llvm-dlltool -l libmyapi.a -d myapi.def
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">clang --ld-path=$(which boflink) --target=x86_64-windows-gnu -nostartfiles -Wl,--custom-api=libmyapi.a -o custom-api.bof custom-api.c
</span></span></code></pre></div><p>MSVC</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-txt" data-lang="txt"><span class="line"><span class="cl">lib /machine:x64 /def:myapi.def /out:myapi.lib
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">cl /GS- /c /Fo:custom-api.obj custom-api.c
</span></span><span class="line"><span class="cl">boflink --custom-api myapi.lib -o custom-api.bof custom-api.obj
</span></span></code></pre></div><p>The <code>--custom-api</code> command flag also provides some flexibility on how Boflink finds the import library. It can either be the path to the import library on disk or the name of a link library for Boflink to search for in the list of library search paths.</p>
<p>If the custom API import library is a part of some packaged tool chain stored at <code>/toolchains/myapi/lib/libmyapi.a</code>, then it can be linked to using the following command line flags.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-txt" data-lang="txt"><span class="line"><span class="cl">x86_64-w64-mingw32-gcc -B ~/.local/libexec/boflink -fno-lto -nostartfiles -Wl,--custom-api=myapi -o custom-api.bof custom-api.c -L /toolchains/myapi/lib
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">boflink -o custom-api.bof custom-api.o –custom-api myapi -L /toolchains/myapi/lib
</span></span></code></pre></div><p>Boflink will add the <code>/toolchains/myapi/lib</code> search path to its list of link library search paths and search for the <code>libmyapi.a</code> library.</p>
<h3 id="link-graph-visualization">Link Graph Visualization</h3>
<p>Internally, Boflink creates a directed graph that is used for performing various linking operations. During the course of development, it became useful to visualize this graph with an external tool.</p>
<p>The <code>--dump-link-graph</code> flag will write out the state of the link graph in <a href="https://graphviz.org/doc/info/lang.html" target="_blank" rel="noopener noreffer ">GraphViz DOT format</a> to the file specified.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-txt" data-lang="txt"><span class="line"><span class="cl">x86_64-w64-mingw32-gcc -B ~/.local/libexec/boflink -fno-lto -nostartfiles -Wl,--dump-link-graph=graph.dot -o example.bof example.c
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">clang --ld-path=$(which boflink) --target=x86_64-windows-gnu -nostartfiles -Wl,--dump-link-graph=graph.dot -o example.bof example.c
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">boflink --dump-link-graph graph.dot -o example.bof example.c
</span></span></code></pre></div><p>This will create a file named <code>graph.dot</code> which is a plaintext GraphViz dot file containing the link graph. The <code>dot</code> command line tool can be used to render this file into an SVG or PNG file so it can be examined using an image viewer or web browser.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-txt" data-lang="txt"><span class="line"><span class="cl"># Installing the Graphviz dot command line tool
</span></span><span class="line"><span class="cl">sudo apt install graphviz
</span></span><span class="line"><span class="cl">winget install –id Graphviz.Graphviz
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"># Converting to an SVG
</span></span><span class="line"><span class="cl">dot -Tsvg graph.dot -o graph.svg
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"># Converting to a PNG
</span></span><span class="line"><span class="cl">dot -Tpng graph.dot -o graph.png
</span></span></code></pre></div><p>This feature does not add anything feature-wise to the linked BOF but may be useful as a tool for debugging.</p>
<h2 id="msvcrt-pitfalls">MSVCRT Pitfalls</h2>
<p>It is fairly common for BOF developers to include and use C standard library functions from <code>msvcrt.dll</code> in their BOFs. The issue with using msvcrt.dll is that Microsoft basically abandoned all support for it back in 2010 since it had many incompatibilities with C89 (yes, the C standard released in 1989) and it could not add C89 support without breaking ABI compatibility. Microsoft does not even ship an import library for it and has not for a while now.</p>
<p>This means that you cannot link with <code>msvcrt.dll</code> on Windows without creating a custom import library for it. Even if you do decide to use <code>msvcrt.dll</code>, the functions contained are not compatible with C89 so the C standard library functions defined in the header files Microsoft provides may not be valid for it.</p>
<p>On the MinGW side, MinGW’s solution for dealing with the <code>msvcrt.dll</code> issues is to basically not deal with it at all. If you try to link with certain functions from <code>msvcrt.dll</code> using MinGW, MinGW will instead statically link their own implementation instead. This is so that you do not accidentally shoot yourself in the foot trying to use some C standard library function without knowing that the implementation for it inside <code>msvcrt.dll</code> is completely different than the header definition for it.</p>
<p>The solution for this with Boflink is to use UCRT instead. UCRT is the replacement for <code>msvcrt.dll</code> and is installed by default starting with Windows 10. Boflink supports linking with the UCRT both on Windows with MSVC and using MinGW.</p>
<p>As for UCRT support with BOF loaders, I am not sure how every single BOF loader is implemented so it may vary. I do know that <a href="https://github.com/trustedsec/COFFLoader" target="_blank" rel="noopener noreffer ">TrustedSec’s COFFLoader</a> has worked when using UCRT in some of my testing.</p>
<p>To link with UCRT on Windows pass <code>-lucrt</code> as an additional link flag for finding C standard library functions.</p>
<p>MinGW ships a separate UCRT toolchain with UCRT support. It includes <code>x86_64-w64-mingw32ucrt-gcc</code> as a separate compiler instead of <code>x86_64-w64-mingw32-gcc</code>. Using <code>x86_64-w64-mingw32ucrt-gcc</code> will link with UCRT.</p>
<p>Linking against <code>msvcrt.dll</code> is highly discouraged due to the pitfalls stated above. If using UCRT is not an option, it is recommended to try and find alternative functions from <a href="https://learn.microsoft.com/en-us/windows/win32/api/shlwapi/" target="_blank" rel="noopener noreffer ">shlwapi.h</a> or <a href="https://learn.microsoft.com/en-us/windows/win32/api/strsafe/" target="_blank" rel="noopener noreffer ">strsafe.h</a>. Another option is to use compiler intrinsic functions if the compiler includes them.</p>
<p>This may be rather inconvenient to many people who are used to using <code>msvcrt.dll</code> in their BOFs. Seeing that it is <a href="https://grep.app/search?f.lang=C&amp;regexp=true&amp;q=MSVCRT%5C%24.%2B%3F%5C%28" target="_blank" rel="noopener noreffer ">very prevalent</a> in many open source BOFs, I did spend a lot of time figuring out how to add some support for it as a fallback. I could not figure out a good solution that would work in a non-intrusive way and since Microsoft has been trying to migrate to UCRT, supporting that is a better option.</p>
<h2 id="language-support">Language Support</h2>
<p>Boflink was developed and tested with BOFs written in C. This is because C is by far the most common language used when developing BOFs. Languages outside of C, such as C++, have not been tested at all with Boflink.</p>
<p>That being said, some C++ <em>may</em> work currently but since it has not been tested, the state of C++ support is unknown. Most of the COFF spec is implemented in Boflink but there may be some edge cases with C++ compilers that Boflink does not handle properly. On top of this, there are some language features in C++ which cannot be expressed properly in a COFF. Those features would require some form of runtime initialization to happen either during startup or with the BOF loader.</p>
<h2 id="conclusion">Conclusion</h2>
<p>This project was designed with the goal to help streamline the BOF development process. There are many aspects with BOF development that are notoriously tedious and can make it somewhat more difficult. On the fly capability development has become an increasingly more demanding task. Time and research spent on further streamlining the development process is often neglected but can provide a lot of long term value.</p>
<p>As an aside, some people may be asking: “Isn’t this tool a little bit overkill for typical BOF development scenarios?”. Yes, I absolutely agree that this is a pretty over the top solution for the current issues BOF developers face. This project was also a personal research project for me to understand more about how linkers work. I decided to use Beacon Object Files for this since it can provide some value as a development tool and writing a linker for BOFs is a lot simpler than for full executables.</p>
]]></description></item><item><title>Embedding Files in C/C++ Programs</title><link>https://blog.cybershenanigans.space/posts/embedding-files-in-c-cpp-programs/</link><pubDate>Mon, 13 Jan 2025 00:00:00 +0000</pubDate><author>Matt Ehrnschwender</author><guid>https://blog.cybershenanigans.space/posts/embedding-files-in-c-cpp-programs/</guid><description><![CDATA[<h2 id="background">Background</h2>
<p>Recently, I came across a post on X by <a href="https://x.com/0xTriboulet" target="_blank" rel="noopener noreffer ">@0xTriboulet</a> asking how to deal with large header files in Visual Studio projects <a href="https://x.com/0xTriboulet/status/1878139439714558169" target="_blank" rel="noopener noreffer ">https://x.com/0xTriboulet/status/1878139439714558169</a>.</p>
<p></p>
<p><em><del>intelligence</del> intellisense</em></p>
<p>Based on this post and the rest of the thread, I assume that they were attempting to insert the binary data from a file in their program by converting it into a large C byte array and then pasting that array into a header file.</p>
<p>This is a very common method of embedding binary data from a file inside a C/C++ project. The file data gets converted to hex or decimal and wrapped inside a C array.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#ifndef MYFILE_HEADER_H
</span></span></span><span class="line"><span class="cl"><span class="cp">#define MYFILE_HEADER_H
</span></span></span><span class="line"><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="cl"><span class="k">const</span> <span class="kt">unsigned</span> <span class="kt">char</span> <span class="n">MYFILE_DATA</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span> <span class="mh">0x41</span><span class="p">,</span> <span class="mh">0x41</span><span class="p">,</span> <span class="mh">0x41</span><span class="p">,</span> <span class="mh">0x41</span><span class="p">,</span> <span class="mh">0x41</span><span class="p">,</span> <span class="mh">0x41</span><span class="p">,</span> <span class="p">...</span> <span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="cp">#endif </span><span class="c1">// MYFILE_HEADER_H
</span></span></span></code></pre></div><p>Although this does work, it can lead to some issues with code analysis tools, like auto completion, when they attempt to process this file.</p>
<p>An alternative method of embedding files in a C/C++ program is by skipping the source code part altogether and instead convert the needed file directly into an object file that can be linked in at build time.</p>
<hr>
<h2 id="tl-dr">TL; DR</h2>
<p>GNU/MinGW <code>ld</code> can generate an object file from arbitrary binary data using the <code>-r</code> and <code>-b binary</code> options. This object file will export a few symbols named <code>_binary_FILENAME_start</code>, <code>_binary_FILENAME_end</code>, and <code>_binary_FILENAME_size</code> which can be used to reference the embedded data.</p>
<p>More information can be found in this <a href="https://stackoverflow.com/questions/2627004/embedding-binary-blobs-using-gcc-mingw" target="_blank" rel="noopener noreffer ">StackOverflow thread</a>.</p>
<p>A script or other tools can also be used to generate object files with other files embedded into it.</p>
<hr>
<h2 id="generating-coffs-with-ld">Generating COFFs with ld</h2>
<p>This method only<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup> works with GNU/MinGW <a href="https://ftp.gnu.org/old-gnu/Manuals/ld-2.9.1/html_mono/ld.html" target="_blank" rel="noopener noreffer ">ld</a> and LLVM <a href="https://lld.llvm.org/" target="_blank" rel="noopener noreffer ">lld</a>. These linkers support different targets which determine what type of object files they are capable of generating. The target formats supported by both GNU/MinGW <code>ld</code> and LLVM <code>lld</code> are listed in the <code>--help</code> output of each program.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl"><span class="c1"># GNU ld</span>
</span></span><span class="line"><span class="cl">ld --help <span class="p">|</span> grep <span class="s1">&#39;supported targets&#39;</span>
</span></span><span class="line"><span class="cl">ld: supported targets: elf64-x86-64 elf32-i386 elf32-iamcu elf32-x86-64 pei-i386 pe-x86-64 pei-x86-64 elf64-little elf64-big elf32-little elf32-big pe-bigobj-x86-64 pe-i386 pdb elf64-bpfle elf64-bpfbe srec symbolsrec verilog tekhex binary ihex plugin
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl"><span class="c1"># LLVM lld</span>
</span></span><span class="line"><span class="cl">ld.lld --help <span class="p">|</span> grep <span class="s1">&#39;supported targets&#39;</span>
</span></span><span class="line"><span class="cl">ld.lld: supported targets: elf
</span></span></code></pre></div><p>The target format can be specified using the <code>--oformat</code> flag on the command line. These linkers also support another flag, <code>-r</code>, which specifies that they should generate a relocatable object file as output instead of a typical executable or shared library. The <code>-b</code> option is used to specify the type of input file.</p>
<p>Here is how a COFF can be generated using <code>ld</code> with the contents of an arbitrary file embedded inside it.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">matt@laptop :: ~ &gt;&gt; cat hello.txt
</span></span><span class="line"><span class="cl">Hello World
</span></span><span class="line"><span class="cl">matt@laptop :: ~ &gt;&gt; ld -r --oformat pe-x86-64 -b binary -o hello.o hello.txt
</span></span><span class="line"><span class="cl">matt@laptop :: ~ &gt;&gt; file hello.o
</span></span><span class="line"><span class="cl">hello.o: Intel amd64 COFF object file, no relocation info, no line number info, not stripped, <span class="m">1</span> section, symbol <span class="nv">offset</span><span class="o">=</span>0x4c, <span class="m">3</span> symbols, 1st section name <span class="s2">&#34;.data&#34;</span>
</span></span><span class="line"><span class="cl">matt@laptop :: ~ &gt;&gt;
</span></span></code></pre></div><p>MinGW <code>ld</code> can also do the same but without needing the <code>--oformat</code> since it produces COFFs by default.</p>
<p>Along with the embedded file data, the COFF will also contain a set of symbols that can be used for referencing that data. These symbols can be viewed using any generic tool that is capable of displaying the symbol table of a COFF. One such tool is <a href="https://book.rada.re/tools/rabin2/intro.html" target="_blank" rel="noopener noreffer ">rabin2</a>.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">matt@laptop :: ~ &gt;&gt; rabin2 -s hello.o
</span></span><span class="line"><span class="cl"><span class="o">[</span>Symbols<span class="o">]</span>
</span></span><span class="line"><span class="cl">nth paddr      vaddr      <span class="nb">bind</span>   <span class="nb">type</span> size lib name                    demangled
</span></span><span class="line"><span class="cl">――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
</span></span><span class="line"><span class="cl"><span class="m">0</span>   0x0000003c 0x00000000 GLOBAL UNK  <span class="m">4</span>        _binary_hello_txt_start
</span></span><span class="line"><span class="cl"><span class="m">0</span>   0x00000000 0x00000000 GLOBAL UNK  <span class="m">4</span>        _binary_hello_txt_size
</span></span><span class="line"><span class="cl"><span class="m">0</span>   0x00000048 0x0000000c GLOBAL UNK  <span class="m">4</span>        _binary_hello_txt_end
</span></span></code></pre></div><p>The symbol names are derived from the name of the input file passed into <code>ld</code>.</p>
<hr>
<h3 id="using-ld-generated-coffs">Using ld Generated COFFs</h3>
<p>Now in the C/C++ program, the file data can be referenced through those exported symbols.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="cl"><span class="k">extern</span> <span class="kt">unsigned</span> <span class="kt">char</span> <span class="n">_binary_hello_txt_start</span><span class="p">[];</span>
</span></span><span class="line"><span class="cl"><span class="k">extern</span> <span class="kt">unsigned</span> <span class="kt">char</span> <span class="n">_binary_hello_txt_end</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="k">extern</span> <span class="kt">unsigned</span> <span class="kt">char</span> <span class="n">_binary_hello_txt_size</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;Array: %p</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">_binary_hello_txt_start</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;Array end: %p</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">_binary_hello_txt_end</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;Array size: %llu</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">_binary_hello_txt_size</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>There are three important things worth mentioning here:</p>
<ol>
<li>The file data is not guaranteed to be NULL terminated. If the data is being used as a string, a NULL terminator should be manually inserted to ensure that it is present. <code>ld</code> will pad the section with NULL bytes to match the specified alignment (16 bytes) but will not add this padding if it is not needed. The NULL terminator can be added either before the input file is passed through <code>ld</code> or during <a href="##object-post-processing" rel="">post-processing</a>.</li>
<li>The <code>_binary_hello_txt_end</code> symbol is the first byte past the end of the file data. A <code>&amp;</code> is needed to get the address of it.</li>
<li>The <code>_binary_hello_txt_size</code> symbol is a little weird. The actual size of the file data is the address of the symbol and not the symbol itself. This is why the <code>&amp;</code> is needed to get the array size. It may be easier to create a macro that derives the size of the file data based on the start and end addresses of the array.</li>
</ol>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="cl"><span class="k">extern</span> <span class="kt">unsigned</span> <span class="kt">char</span> <span class="n">_binary_hello_txt_start</span><span class="p">[];</span>
</span></span><span class="line"><span class="cl"><span class="k">extern</span> <span class="kt">unsigned</span> <span class="kt">char</span> <span class="n">_binary_hello_txt_end</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="cp">#define hello_txt_size (&amp;_binary_hello_txt_end - _binary_hello_txt_start)
</span></span></span><span class="line"><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;Array size: %llu</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">hello_txt_size</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>The object file with the embedded file data can be linked in as is without needing to add any special link flags.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">x86_64-w64-mingw32-gcc -o main.exe main.c hello.o
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Or with clang</span>
</span></span><span class="line"><span class="cl">clang --target<span class="o">=</span>x86_64-windows-gnu -o main.exe main.c hello.o
</span></span></code></pre></div><p>This method of embedding arbitrary file data into a C/C++ program is a lot nicer since it does not require any extra developer tooling and eliminates the need to generate a source file for the embedded data.</p>
<hr>
<h3 id="object-post-processing">Object Post-Processing</h3>
<p>Some post-processing may be needed in order to get the object file in a more desirable state. This can be done with <a href="https://ftp.gnu.org/old-gnu/Manuals/binutils-2.12/html_node/binutils_5.html" target="_blank" rel="noopener noreffer ">objcopy</a> or various other custom tools.</p>
<p>Here are some example scenarios where objcopy can be used to make these modifications.</p>
<h4 id="renaming-the-exported-symbols">Renaming the Exported Symbols</h4>
<p>The auto-generated symbol names can be renamed using the <code>--redefine-sym</code> flag.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">objcopy <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>	--redefine-sym <span class="nv">_binary_hello_txt_start</span><span class="o">=</span>hello_data_start <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>	--redefine-sym <span class="nv">_binary_hello_txt_end</span><span class="o">=</span>hello_data_end <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>	--redefine-sym <span class="nv">_binary_hello_txt_size</span><span class="o">=</span>hello_data_size <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>	hello.o
</span></span></code></pre></div><h4 id="removing-the-_size-symbol">Removing the _size Symbol</h4>
<p>If the <code>*_size</code> symbol or any other symbol is not needed, it can be removed from the COFF.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">objcopy -N _binary_hello_txt_size hello.o
</span></span></code></pre></div><h4 id="adding-a-trailing-null-byte">Adding a Trailing NULL Byte</h4>
<p>A trailing NULL byte can be added at the end of the file data if it is being used as a string. This is done by creating a temporary file with the extracted section data, adding the trailing NULL byte to it, and then reinserting it back into the COFF.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl"><span class="nb">export</span> <span class="nv">SECTION_TMPFILE</span><span class="o">=</span><span class="k">$(</span>mktemp -t -p /tmp objcopy-section.XXXXX<span class="k">)</span>
</span></span><span class="line"><span class="cl">objcopy --dump-section .data<span class="o">=</span><span class="nv">$SECTION_TMPFILE</span> hello.o
</span></span><span class="line"><span class="cl"><span class="nb">printf</span> <span class="s1">&#39;\0&#39;</span> &gt;&gt; <span class="nv">$SECTION_TMPFILE</span>
</span></span><span class="line"><span class="cl">objcopy --update-section .data<span class="o">=</span><span class="nv">$SECTION_TMPFILE</span> hello.o
</span></span><span class="line"><span class="cl">rm <span class="nv">$SECTION_TMPFILE</span>
</span></span><span class="line"><span class="cl"><span class="nb">unset</span> SECTION_TMPFILE
</span></span></code></pre></div><h4 id="changing-the-section-of-the-file-data">Changing the Section of the File Data</h4>
<p><code>ld</code> by default will insert the file into the <code>.data</code> section. This can be changed to a different section if desired.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">objcopy --rename-section .data<span class="o">=</span>.rdata hello.o
</span></span></code></pre></div><p>The section flags will automatically be adjusted if the new section name is a standard section name. If the section flags need to be manually adjusted for custom sections, they can be specified using the <code>--set-section-flags</code> option or in the <code>--rename-section</code> option.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">objcopy --rename-section .data<span class="o">=</span>custom hello.o
</span></span><span class="line"><span class="cl">objcopy --set-section-flags <span class="nv">custom</span><span class="o">=</span>alloc,load,readonly,data,contents hello.o
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Changing the flags during renaming</span>
</span></span><span class="line"><span class="cl">objcopy --rename-section .data<span class="o">=</span>custom,alloc,load,readonly,data,contents hello.o
</span></span></code></pre></div><p>The flag values are listed under the <code>--set-section-flags</code> option in the <a href="https://man7.org/linux/man-pages/man1/objcopy.1.html" target="_blank" rel="noopener noreffer ">objcopy man page</a>.</p>
<hr>
<h2 id="generating-coffs-from-scratch">Generating COFFs from Scratch</h2>
<p><code>ld</code> and <code>objcopy</code> provide a ton of flexibility for converting arbitrary binary data files into linkable object files. One of the disadvantages is that this file embedding workflow is not ideal for Windows environments. MSVC&rsquo;s <code>link.exe</code> is unable to generate an object file from an arbitrary binary input file and LLVM <code>lld</code> only supports generating ELFs<sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup>. The Windows version of LLVM <code>lld</code> bundled with Visual Studio also does not support the <code>-r</code> or <code>-b</code> flags.</p>
<p>There are many existing tools publicly available that work on Windows and can generate COFFs from an arbitrary binary file. These can be found by searching for &ldquo;bin2obj&rdquo; or &ldquo;bin2coff&rdquo; programs online.</p>
<p>Writing a custom tool for this can provide a lot more flexibility than what existing implementations may offer.</p>
<p>It may seem a little complicated at first; however, COFFs are a pretty straightforward file format and the lack of relocations makes things slightly easier.</p>
<p>The <a href="/posts/writing-bofs-without-dfr" rel="">&ldquo;Writing Beacon Object Files Without DFR&rdquo;</a> blog post starting from the <a href="/posts/writing-bofs-without-dfr/#so-how-does-this-work" rel="">&ldquo;So How Does This Work?&rdquo;</a> section contains an in-depth walk through on the COFF file structure which provides some good background on this.</p>
<h3 id="looking-at-the-coff-generated-by-ld">Looking at the COFF Generated by ld</h3>
<p>Analyzing the COFFs generated by <code>ld</code> can help with understanding what is all involved to accomplish this.</p>
<p>This will create a basic test COFF for exploring.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;Hello World&#34;</span> &gt; hello.txt
</span></span><span class="line"><span class="cl">ld -r --oformat pe-x86-64 -b binary -o hello.o hello.txt
</span></span></code></pre></div><p>Here is the hex-dump of the generated COFF.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-txt" data-lang="txt"><span class="line"><span class="cl">00000000: 6486 0100 0000 0000 4c00 0000 0300 0000  d.......L.......
</span></span><span class="line"><span class="cl">00000010: 0000 0500 2e64 6174 6100 0000 0000 0000  .....data.......
</span></span><span class="line"><span class="cl">00000020: 0000 0000 1000 0000 3c00 0000 0000 0000  ........&lt;.......
</span></span><span class="line"><span class="cl">00000030: 0000 0000 0000 0000 4000 50c0 4865 6c6c  ........@.P.Hell
</span></span><span class="line"><span class="cl">00000040: 6f20 576f 726c 640a 0000 0000 0000 0000  o World.........
</span></span><span class="line"><span class="cl">00000050: 0400 0000 0000 0000 0100 0000 0200 0000  ................
</span></span><span class="line"><span class="cl">00000060: 0000 1c00 0000 0c00 0000 ffff 0000 0200  ................
</span></span><span class="line"><span class="cl">00000070: 0000 0000 3300 0000 0c00 0000 0100 0000  ....3...........
</span></span><span class="line"><span class="cl">00000080: 0200 4900 0000 5f62 696e 6172 795f 6865  ..I..._binary_he
</span></span><span class="line"><span class="cl">00000090: 6c6c 6f5f 7478 745f 7374 6172 7400 5f62  llo_txt_start._b
</span></span><span class="line"><span class="cl">000000a0: 696e 6172 795f 6865 6c6c 6f5f 7478 745f  inary_hello_txt_
</span></span><span class="line"><span class="cl">000000b0: 7369 7a65 005f 6269 6e61 7279 5f68 656c  size._binary_hel
</span></span><span class="line"><span class="cl">000000c0: 6c6f 5f74 7874 5f65 6e64 00              lo_txt_end.
</span></span></code></pre></div><p>It is pretty small with the majority of the file consisting of the COFF&rsquo;s metadata.</p>
<p><a href="https://ghidra-sre.org/" target="_blank" rel="noopener noreffer ">Ghidra</a>, or any other disassembler, can also help with further analyzing it.</p>
<p></p>
<p>This listing display contains the entire COFF. There is a <a href="https://learn.microsoft.com/en-us/windows/win32/debug/pe-format#coff-file-header-object-and-image" target="_blank" rel="noopener noreffer ">COFF File Header</a>, a single <a href="https://learn.microsoft.com/en-us/windows/win32/debug/pe-format#section-table-section-headers" target="_blank" rel="noopener noreffer ">Section Header</a> for the <code>.data</code> section and the file contents inside the <code>.data</code> section.</p>
<p>The symbol table (<code>Window -&gt; Symbol Table</code>) lists all of the defined symbols.
</p>
<p>These are the symbols that are automatically generated and exported for use inside the main program. The &ldquo;Source&rdquo; column in Ghidra shows them as being &ldquo;Imported&rdquo; but that just means they are defined with <code>IMAGE_SYM_CLASS_EXTERNAL</code> <a href="https://learn.microsoft.com/en-us/windows/win32/debug/pe-format#storage-class" target="_blank" rel="noopener noreffer ">storage class</a>.</p>
<p>The relocations (<code>Window -&gt; Relocation Table</code>) window will show 0 relocations because there are no references in this COFF that reference external data or data in other sections.</p>
<p>This COFF information can be laid out linearly as it is in the file but with the values for each structure filled in.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cm">/** COFF File header */</span>
</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="n">COFFFileHeader</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">Machine</span> <span class="o">=</span> <span class="n">IMAGE_FILE_MACHINE_AMD64</span><span class="p">,</span> <span class="cm">/* 0x8664 */</span>
</span></span><span class="line"><span class="cl">    <span class="n">NumberOfSections</span> <span class="o">=</span> <span class="mi">1</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">TimeDateStamp</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">PointerToSymbolTable</span> <span class="o">=</span> <span class="mh">0x4c</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">NumberOfSymbols</span> <span class="o">=</span> <span class="mi">3</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">SizeOfOptionalHeader</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">Characteristics</span> <span class="o">=</span> <span class="n">IMAGE_FILE_RELOCS_STRIPPED</span> <span class="o">|</span> <span class="n">IMAGE_FILE_LINE_NUMS_STRIPPED</span><span class="p">,</span> <span class="cm">/* 0x5 */</span>
</span></span><span class="line"><span class="cl"><span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="cm">/** Section Table (Section Headers) */</span>
</span></span><span class="line"><span class="cl"><span class="cm">/* Only 1 section header in the section table */</span>
</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="n">COFFSectionHeader</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">Name</span> <span class="o">=</span> <span class="s">&#34;.data&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">VirtualSize</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">VirtualAddress</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">SizeOfRawData</span> <span class="o">=</span> <span class="mh">0x10</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">PointerToRawData</span> <span class="o">=</span> <span class="mh">0x3c</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">PointerToRelocations</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">PointerToLineNumbers</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">NumberOfRelocations</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">NumberOfLineNumbers</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">Characteristics</span> <span class="o">=</span> <span class="n">IMAGE_SCN_CNT_INITIALIZED_DATA</span> <span class="o">|</span> <span class="n">IMAGE_SCN_ALIGN_16BYTES</span> <span class="o">|</span> <span class="n">IMAGE_SCN_MEM_READ</span> <span class="o">|</span> <span class="n">IMAGE_SCN_MEM_WRITE</span><span class="p">,</span> <span class="cm">/* 0xc0500040 */</span>
</span></span><span class="line"><span class="cl"><span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="cm">/** The embedded file&#39;s contents are located here after the section header and padded with NULL bytes */</span>
</span></span><span class="line"><span class="cl"><span class="s">&#34;Hello World&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="cm">/** COFF Symbol Table (3 symbols) */</span>
</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="n">COFFSymbol</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">Name</span> <span class="o">=</span> <span class="s">&#34;_binary_hello_txt_start&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">Value</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">SectionNumber</span> <span class="o">=</span> <span class="mi">1</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">Type</span> <span class="o">=</span> <span class="n">IMAGE_SYM_DTYPE_NULL</span> <span class="o">|</span> <span class="n">IMAGE_SYM_TYPE_NULL</span><span class="p">,</span> <span class="cm">/* 0x0 */</span>
</span></span><span class="line"><span class="cl">    <span class="n">StorageClass</span> <span class="o">=</span> <span class="n">IMAGE_SYM_CLASS_EXTERNAL</span><span class="p">,</span> <span class="cm">/* 0x2 */</span>
</span></span><span class="line"><span class="cl">    <span class="n">NumberOfAuxSymbols</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"><span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="n">COFFSymbol</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">Name</span> <span class="o">=</span> <span class="s">&#34;_binary_hello_txt_size&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">Value</span> <span class="o">=</span> <span class="mh">0xc</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">SectionNumber</span> <span class="o">=</span> <span class="n">IMAGE_SYM_ABSOLUTE</span><span class="p">,</span> <span class="cm">/* -1 */</span>
</span></span><span class="line"><span class="cl">    <span class="n">Type</span> <span class="o">=</span> <span class="n">IMAGE_SYM_DTYPE_NULL</span> <span class="o">|</span> <span class="n">IMAGE_SYM_TYPE_NULL</span><span class="p">,</span> <span class="cm">/* 0x0 */</span>
</span></span><span class="line"><span class="cl">    <span class="n">StorageClass</span> <span class="o">=</span> <span class="n">IMAGE_SYM_CLASS_EXTERNAL</span><span class="p">,</span> <span class="cm">/* 0x2 */</span>
</span></span><span class="line"><span class="cl">    <span class="n">NumberOfAuxSymbols</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"><span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="n">COFFSymbol</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">Name</span> <span class="o">=</span> <span class="s">&#34;_binary_hello_txt_end&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">Value</span> <span class="o">=</span> <span class="mh">0xc</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">SectionNumber</span> <span class="o">=</span> <span class="mi">1</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">Type</span> <span class="o">=</span> <span class="n">IMAGE_SYM_DTYPE_NULL</span> <span class="o">|</span> <span class="n">IMAGE_SYM_TYPE_NULL</span><span class="p">,</span> <span class="cm">/* 0x0 */</span>
</span></span><span class="line"><span class="cl">    <span class="n">StorageClass</span> <span class="o">=</span> <span class="n">IMAGE_SYM_CLASS_EXTERNAL</span><span class="p">,</span> <span class="cm">/* 0x2 */</span>
</span></span><span class="line"><span class="cl">    <span class="n">NumberOfAuxSymbols</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"><span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="cm">/* String table */</span>
</span></span></code></pre></div><p>One thing missing from this is the COFF&rsquo;s string table. The string table contains the string values from the <code>Name</code> fields in the <code>COFFSymbol</code> structures. They are stored there because those strings are longer than 8 bytes. More information on how the string table is utilized can also be found in the <a href="/posts/writing-bofs-without-dfr/#so-how-does-this-work" rel="">&ldquo;So How Does This Work?&rdquo;</a> section from the <a href="/posts/writing-bofs-without-dfr" rel="">&ldquo;Writing Beacon Object Files Without DFR&rdquo;</a> post.</p>
<p>In the <code>_binary_hello_txt_size</code> symbol, the value is set to the size of the file data and the symbol&rsquo;s section value is set to <code>IMAGE_SYM_ABSOLUTE</code>. This is where the weirdness with that symbol mentioned above comes from and why you need to reference the symbol&rsquo;s address to get the actual value. There is a way to fix that mentioned later in the <a href="#fixing-the-_size-symbol" rel="">&ldquo;Fixing the _size Symbol&rdquo;</a> section.</p>
<p>The parts that will vary in this metadata are the <code>PointerToSymbolTable</code> field in the <code>COFFFileHeader</code>, the <code>SizeOfRawData</code> field in the <code>COFFSectionHeader</code>, and the <code>Value</code> fields in the <code>_binary_hello_txt_size</code> and <code>_binary_hello_txt_end</code> symbols. They change based on the size of the file being embedded.</p>
<p>There are some patterns with this data. The <code>PointerToSymbolTable</code> field in the <code>COFFFileHeader</code> structure is actually the <code>PointerToRawData</code> field from the <code>COFFSectionHeader</code> structure plus the size of the embedded file itself. The <code>SizeOfRawData</code> field in the <code>COFFSectionHeader</code> is the file size rounded up to the next multiple of the alignment specified in the <code>Characteristics</code> field (<code>IMAGE_SCN_ALIGN_16BYTES</code> 16 bytes). The section data is padded with NULL bytes at the end to reach this size. The <code>Value</code> fields in the <code>_binary_hello_txt_size</code> and <code>_binary_hello_txt_end</code> <code>COFFSymbol</code>s are the same and are just the size of the file.</p>
<p>Ultimately, the COFF consists of the structures above laid out in the order below with the file data embedded somewhere in the center.</p>
<ul>
<li>COFF File Header</li>
<li>Section header for the <code>.data</code> section</li>
<li>Embedded file&rsquo;s data padded with NULL bytes to reach the specified alignment</li>
<li>The <code>COFFSymbol</code> structure array</li>
<li>The string table</li>
</ul>
<h3 id="fixing-the-_size-symbol">Fixing the _size Symbol</h3>
<p>The way the <code>*_size</code> symbol is defined is a little bit inconvenient to work with when referencing it in a program. A simple way of fixing this is to append the file&rsquo;s size at the end of the section and set the <code>*_size</code> symbol to reference that value. Another way is to create a new <code>.rdata</code> section with the file size and have the symbol reference that value.</p>
<p>Here is what the former looks like.</p>
<p>Current layout of the file data and symbol table.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cm">/* The section data as a hexdump */</span>
</span></span><span class="line"><span class="cl"><span class="mo">00000000</span><span class="o">:</span> <span class="mi">4865</span> <span class="mi">6</span><span class="n">c6c</span> <span class="mf">6f</span><span class="mi">20</span> <span class="mf">576f</span> <span class="mi">726</span><span class="n">c</span> <span class="mi">640</span><span class="n">a</span> <span class="mo">0000</span> <span class="mo">0000</span>  <span class="n">Hello</span> <span class="n">World</span><span class="p">.....</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="cm">/* The symbol table */</span>
</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="n">COFFSymbol</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">Name</span> <span class="o">=</span> <span class="s">&#34;_binary_hello_txt_start&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">Value</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">SectionNumber</span> <span class="o">=</span> <span class="mi">1</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">Type</span> <span class="o">=</span> <span class="n">IMAGE_SYM_DTYPE_NULL</span> <span class="o">|</span> <span class="n">IMAGE_SYM_TYPE_NULL</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">StorageClass</span> <span class="o">=</span> <span class="n">IMAGE_SYM_CLASS_EXTERNAL</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">NumberOfAuxSymbols</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"><span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="n">COFFSymbol</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">Name</span> <span class="o">=</span> <span class="s">&#34;_binary_hello_txt_size&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">Value</span> <span class="o">=</span> <span class="mh">0xc</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">SectionNumber</span> <span class="o">=</span> <span class="n">IMAGE_SYM_ABSOLUTE</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">Type</span> <span class="o">=</span> <span class="n">IMAGE_SYM_DTYPE_NULL</span> <span class="o">|</span> <span class="n">IMAGE_SYM_TYPE_NULL</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">StorageClass</span> <span class="o">=</span> <span class="n">IMAGE_SYM_CLASS_EXTERNAL</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">NumberOfAuxSymbols</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"><span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="n">COFFSymbol</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">Name</span> <span class="o">=</span> <span class="s">&#34;_binary_hello_txt_end&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">Value</span> <span class="o">=</span> <span class="mh">0xc</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">SectionNumber</span> <span class="o">=</span> <span class="mi">1</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">Type</span> <span class="o">=</span> <span class="n">IMAGE_SYM_DTYPE_NULL</span> <span class="o">|</span> <span class="n">IMAGE_SYM_TYPE_NULL</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">StorageClass</span> <span class="o">=</span> <span class="n">IMAGE_SYM_CLASS_EXTERNAL</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">NumberOfAuxSymbols</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"><span class="p">};</span>
</span></span></code></pre></div><p>New layout with the file size added in.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cm">/* The section data as a hexdump */</span>
</span></span><span class="line"><span class="cl"><span class="mo">00000000</span><span class="o">:</span> <span class="mi">4865</span> <span class="mi">6</span><span class="n">c6c</span> <span class="mf">6f</span><span class="mi">20</span> <span class="mf">576f</span> <span class="mi">726</span><span class="n">c</span> <span class="mi">640</span><span class="n">a</span> <span class="mo">0000</span> <span class="mo">0000</span>  <span class="n">Hello</span> <span class="n">World</span><span class="p">.....</span>
</span></span><span class="line"><span class="cl"><span class="mo">00000010</span><span class="o">:</span> <span class="mi">0</span><span class="n">c00</span> <span class="mo">0000</span> <span class="mo">0000</span> <span class="mo">0000</span> <span class="mo">0000</span> <span class="mo">0000</span> <span class="mo">0000</span> <span class="mo">0000</span>  <span class="p">................</span> <span class="c1">// Size of the file (0xc) in little endian and added at the end with some NULL byte padding.
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>
</span></span><span class="line"><span class="cl"><span class="cm">/* The symbol table */</span>
</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="n">COFFSymbol</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">Name</span> <span class="o">=</span> <span class="s">&#34;_binary_hello_txt_start&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">Value</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">SectionNumber</span> <span class="o">=</span> <span class="mi">1</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">Type</span> <span class="o">=</span> <span class="n">IMAGE_SYM_DTYPE_NULL</span> <span class="o">|</span> <span class="n">IMAGE_SYM_TYPE_NULL</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">StorageClass</span> <span class="o">=</span> <span class="n">IMAGE_SYM_CLASS_EXTERNAL</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">NumberOfAuxSymbols</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"><span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="n">COFFSymbol</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">Name</span> <span class="o">=</span> <span class="s">&#34;_binary_hello_txt_size&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">Value</span> <span class="o">=</span> <span class="mh">0x10</span><span class="p">,</span> <span class="c1">// Value adjusted to point to the inserted size value in the section
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="n">SectionNumber</span> <span class="o">=</span> <span class="mi">1</span><span class="p">,</span> <span class="c1">// SectionNumber adjusted to reference the section with the size value
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="n">Type</span> <span class="o">=</span> <span class="n">IMAGE_SYM_DTYPE_NULL</span> <span class="o">|</span> <span class="n">IMAGE_SYM_TYPE_NULL</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">StorageClass</span> <span class="o">=</span> <span class="n">IMAGE_SYM_CLASS_EXTERNAL</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">NumberOfAuxSymbols</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"><span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="n">COFFSymbol</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">Name</span> <span class="o">=</span> <span class="s">&#34;_binary_hello_txt_end&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">Value</span> <span class="o">=</span> <span class="mh">0xc</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">SectionNumber</span> <span class="o">=</span> <span class="mi">1</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">Type</span> <span class="o">=</span> <span class="n">IMAGE_SYM_DTYPE_NULL</span> <span class="o">|</span> <span class="n">IMAGE_SYM_TYPE_NULL</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">StorageClass</span> <span class="o">=</span> <span class="n">IMAGE_SYM_CLASS_EXTERNAL</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">NumberOfAuxSymbols</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"><span class="p">};</span>
</span></span></code></pre></div><p>Now, the size of the file data can be referenced without needing to take the address of it.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdint.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="cl"><span class="k">extern</span> <span class="kt">char</span> <span class="n">_binary_hello_txt_start</span><span class="p">[];</span>
</span></span><span class="line"><span class="cl"><span class="k">extern</span> <span class="kt">char</span> <span class="n">_binary_hello_txt_end</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="k">extern</span> <span class="kt">size_t</span> <span class="n">_binary_hello_txt_size</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;Array size: %llu</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">_binary_hello_txt_size</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><h3 id="bin2coffpy">bin2coff.py</h3>
<p>I wrote a small, self-contained python script for generating COFFs that should work on various different platforms (Linux, Windows, Mac, etc.).</p>
<p><a href="https://gist.github.com/MEhrn00/9615b92d9bfd3c85d6cba69edb31387d" target="_blank" rel="noopener noreffer ">https://gist.github.com/MEhrn00/9615b92d9bfd3c85d6cba69edb31387d</a></p>
<h2 id="generating-coffs-from-yaml">Generating COFFs from&hellip; yaml?</h2>
<p>Some people might say that this method is extremely cursed and should not be a thing that <em>actually</em> exists. Others may marvel at its pristine beauty and grasp the true extent of its full potential.</p>
<p>In the LLVM <a href="https://github.com/llvm/llvm-project/tree/main/llvm/tools" target="_blank" rel="noopener noreffer ">toolset</a>, there exists a set of two peculiar tools named <a href="https://llvm.org/docs/yaml2obj.html" target="_blank" rel="noopener noreffer ">yaml2obj</a> and <a href="https://github.com/llvm/llvm-project/tree/main/llvm/tools/obj2yaml" target="_blank" rel="noopener noreffer ">obj2yaml</a>.</p>
<p>As the names may imply, these tools are capable of creating object files from a yaml file that describes its contents.</p>
<p>Here is what that looks like. The yaml description of the <code>hello.o</code> file from above can be printed out using <code>obj2yaml</code>.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">matt@laptop :: ~ &gt;&gt; obj2yaml hello.o
</span></span><span class="line"><span class="cl">--- !COFF
</span></span><span class="line"><span class="cl">header:
</span></span><span class="line"><span class="cl">  Machine:         IMAGE_FILE_MACHINE_AMD64
</span></span><span class="line"><span class="cl">  Characteristics: <span class="o">[</span> IMAGE_FILE_RELOCS_STRIPPED, IMAGE_FILE_LINE_NUMS_STRIPPED <span class="o">]</span>
</span></span><span class="line"><span class="cl">sections:
</span></span><span class="line"><span class="cl">  - Name:            .data
</span></span><span class="line"><span class="cl">    Characteristics: <span class="o">[</span> IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE <span class="o">]</span>
</span></span><span class="line"><span class="cl">    Alignment:       <span class="m">16</span>
</span></span><span class="line"><span class="cl">    SectionData:     48656C6C6F20576F726C640A00000000
</span></span><span class="line"><span class="cl">    SizeOfRawData:   <span class="m">16</span>
</span></span><span class="line"><span class="cl">symbols:
</span></span><span class="line"><span class="cl">  - Name:            _binary_hello_txt_start
</span></span><span class="line"><span class="cl">    Value:           <span class="m">0</span>
</span></span><span class="line"><span class="cl">    SectionNumber:   <span class="m">1</span>
</span></span><span class="line"><span class="cl">    SimpleType:      IMAGE_SYM_TYPE_NULL
</span></span><span class="line"><span class="cl">    ComplexType:     IMAGE_SYM_DTYPE_NULL
</span></span><span class="line"><span class="cl">    StorageClass:    IMAGE_SYM_CLASS_EXTERNAL
</span></span><span class="line"><span class="cl">  - Name:            _binary_hello_txt_size
</span></span><span class="line"><span class="cl">    Value:           <span class="m">12</span>
</span></span><span class="line"><span class="cl">    SectionNumber:   -1
</span></span><span class="line"><span class="cl">    SimpleType:      IMAGE_SYM_TYPE_NULL
</span></span><span class="line"><span class="cl">    ComplexType:     IMAGE_SYM_DTYPE_NULL
</span></span><span class="line"><span class="cl">    StorageClass:    IMAGE_SYM_CLASS_EXTERNAL
</span></span><span class="line"><span class="cl">  - Name:            _binary_hello_txt_end
</span></span><span class="line"><span class="cl">    Value:           <span class="m">12</span>
</span></span><span class="line"><span class="cl">    SectionNumber:   <span class="m">1</span>
</span></span><span class="line"><span class="cl">    SimpleType:      IMAGE_SYM_TYPE_NULL
</span></span><span class="line"><span class="cl">    ComplexType:     IMAGE_SYM_DTYPE_NULL
</span></span><span class="line"><span class="cl">    StorageClass:    IMAGE_SYM_CLASS_EXTERNAL
</span></span><span class="line"><span class="cl">...
</span></span></code></pre></div><p>This yaml data contains all of the information pertaining to this COFF.</p>
<p>A new COFF can be generated by modifying the values in this yaml file or by creating a new yaml file from scratch and then running it through <code>yaml2obj</code>.</p>
<p>For the purpose of embedding files into C/C++ programs, this is achievable with <code>yaml2obj</code>.</p>
<p>The yaml example file above can be used as a template for embedding another file into it. The section data string will need to be replaced with the hex string of the target file for embedding and the other metadata needs to be adjusted to account for the size of the file data. Then, <code>yaml2obj</code> can take the modified yaml file and generate a fresh object file for linking that contains the embedded file data.</p>
<p>This process can be scripted out using something like bash or python.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="cp">#!/bin/bash
</span></span></span><span class="line"><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="o">[</span> <span class="s2">&#34;</span><span class="nv">$#</span><span class="s2">&#34;</span> -ne <span class="m">3</span> <span class="o">]</span><span class="p">;</span> <span class="k">then</span>
</span></span><span class="line"><span class="cl">    <span class="nb">echo</span> <span class="s2">&#34;usage: </span><span class="nv">$0</span><span class="s2"> [INPUT] [OUTPUT] [SYMBOL]&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="nb">exit</span> <span class="m">1</span>
</span></span><span class="line"><span class="cl"><span class="k">fi</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="o">[</span> ! -f <span class="s2">&#34;</span><span class="nv">$1</span><span class="s2">&#34;</span> <span class="o">]</span><span class="p">;</span> <span class="k">then</span>
</span></span><span class="line"><span class="cl">    <span class="nb">echo</span> <span class="s2">&#34;</span><span class="nv">$1</span><span class="s2"> is not a file.&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="nb">exit</span> <span class="m">1</span>
</span></span><span class="line"><span class="cl"><span class="k">fi</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="o">[</span> -z <span class="s2">&#34;</span><span class="nv">$3</span><span class="s2">&#34;</span> <span class="o">]</span><span class="p">;</span> <span class="k">then</span>
</span></span><span class="line"><span class="cl">    <span class="nb">echo</span> <span class="s2">&#34;Symbol is empty.&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="nb">exit</span> <span class="m">1</span>
</span></span><span class="line"><span class="cl"><span class="k">fi</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nv">filesize</span><span class="o">=</span><span class="k">$(</span>ls -l <span class="nv">$1</span> <span class="p">|</span> cut -d<span class="s1">&#39; &#39;</span> -f5<span class="k">)</span>
</span></span><span class="line"><span class="cl"><span class="nv">filehex</span><span class="o">=</span><span class="k">$(</span>xxd -p -u -c0 <span class="nv">$1</span><span class="k">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nv">sectiondata</span><span class="o">=</span><span class="nv">$filehex</span>
</span></span><span class="line"><span class="cl"><span class="nv">sectionsize</span><span class="o">=</span><span class="nv">$filesize</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nv">alignment</span><span class="o">=</span><span class="m">16</span>
</span></span><span class="line"><span class="cl"><span class="nv">remainder</span><span class="o">=</span><span class="k">$((</span><span class="nv">$sectionsize</span> <span class="o">%</span> <span class="nv">$alignment</span><span class="k">))</span>
</span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="o">[</span> <span class="nv">$remainder</span> -ne <span class="m">0</span> <span class="o">]</span><span class="p">;</span> <span class="k">then</span>
</span></span><span class="line"><span class="cl">    <span class="nv">padding</span><span class="o">=</span><span class="k">$((</span><span class="nv">$alignment</span> <span class="o">-</span> <span class="nv">$remainder</span><span class="k">))</span>
</span></span><span class="line"><span class="cl">    <span class="k">for</span> _ in <span class="k">$(</span>seq <span class="nv">$padding</span><span class="k">)</span><span class="p">;</span> <span class="k">do</span>
</span></span><span class="line"><span class="cl">        <span class="nv">sectiondata</span><span class="o">+=</span><span class="s2">&#34;00&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="k">done</span>
</span></span><span class="line"><span class="cl">    <span class="nv">sectionsize</span><span class="o">=</span><span class="k">$((</span><span class="nv">$sectionsize</span> <span class="o">+</span> <span class="nv">$padding</span><span class="k">))</span>
</span></span><span class="line"><span class="cl"><span class="k">fi</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nv">tmp</span><span class="o">=</span><span class="k">$(</span>mktemp -t -p /tmp yaml2obj.XXXXX<span class="k">)</span>
</span></span><span class="line"><span class="cl"><span class="nb">trap</span> <span class="s1">&#39;{ rm -f -- &#34;$tmp&#34;; }&#39;</span> EXIT
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">cat <span class="s">&lt;&lt;EOF &gt; $tmp
</span></span></span><span class="line"><span class="cl"><span class="s">--- !COFF
</span></span></span><span class="line"><span class="cl"><span class="s">header:
</span></span></span><span class="line"><span class="cl"><span class="s">  Machine:         IMAGE_FILE_MACHINE_AMD64
</span></span></span><span class="line"><span class="cl"><span class="s">  Characteristics: [ IMAGE_FILE_RELOCS_STRIPPED, IMAGE_FILE_LINE_NUMS_STRIPPED ]
</span></span></span><span class="line"><span class="cl"><span class="s">sections:
</span></span></span><span class="line"><span class="cl"><span class="s">  - Name:            .data
</span></span></span><span class="line"><span class="cl"><span class="s">    Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
</span></span></span><span class="line"><span class="cl"><span class="s">    Alignment:       16
</span></span></span><span class="line"><span class="cl"><span class="s">    SectionData:     $sectiondata
</span></span></span><span class="line"><span class="cl"><span class="s">    SizeOfRawData:   $sectionsize
</span></span></span><span class="line"><span class="cl"><span class="s">symbols:
</span></span></span><span class="line"><span class="cl"><span class="s">  - Name:            _binary_${3}_start
</span></span></span><span class="line"><span class="cl"><span class="s">    Value:           0
</span></span></span><span class="line"><span class="cl"><span class="s">    SectionNumber:   1
</span></span></span><span class="line"><span class="cl"><span class="s">    SimpleType:      IMAGE_SYM_TYPE_NULL
</span></span></span><span class="line"><span class="cl"><span class="s">    ComplexType:     IMAGE_SYM_DTYPE_NULL
</span></span></span><span class="line"><span class="cl"><span class="s">    StorageClass:    IMAGE_SYM_CLASS_EXTERNAL
</span></span></span><span class="line"><span class="cl"><span class="s">  - Name:            _binary_${3}_size
</span></span></span><span class="line"><span class="cl"><span class="s">    Value:           $filesize
</span></span></span><span class="line"><span class="cl"><span class="s">    SectionNumber:   -1
</span></span></span><span class="line"><span class="cl"><span class="s">    SimpleType:      IMAGE_SYM_TYPE_NULL
</span></span></span><span class="line"><span class="cl"><span class="s">    ComplexType:     IMAGE_SYM_DTYPE_NULL
</span></span></span><span class="line"><span class="cl"><span class="s">    StorageClass:    IMAGE_SYM_CLASS_EXTERNAL
</span></span></span><span class="line"><span class="cl"><span class="s">  - Name:            _binary_${3}_end
</span></span></span><span class="line"><span class="cl"><span class="s">    Value:           $filesize
</span></span></span><span class="line"><span class="cl"><span class="s">    SectionNumber:   1
</span></span></span><span class="line"><span class="cl"><span class="s">    SimpleType:      IMAGE_SYM_TYPE_NULL
</span></span></span><span class="line"><span class="cl"><span class="s">    ComplexType:     IMAGE_SYM_DTYPE_NULL
</span></span></span><span class="line"><span class="cl"><span class="s">    StorageClass:    IMAGE_SYM_CLASS_EXTERNAL
</span></span></span><span class="line"><span class="cl"><span class="s">EOF</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">yaml2obj -o <span class="nv">$2</span> <span class="nv">$tmp</span>
</span></span><span class="line"><span class="cl">rm -f <span class="nv">$tmp</span>
</span></span></code></pre></div><p>This should generate a COFF with the data from the specified file embedded into it.</p>
<p>Unfortunately, <code>yaml2obj</code> does not ship with Visual Studio&rsquo;s clang tools and is not present in the <code>LLVM.LLVM</code> package from winget so it may need to be compiled from source in order to use it on Windows.</p>
<h2 id="build-system-integration">Build System Integration</h2>
<p>It&rsquo;s generally not a good idea to commit binary files into version control unless the the version control system has good support for them. Git has <a href="https://git-lfs.com/" target="_blank" rel="noopener noreffer ">Git LFS</a> for this and is available on <a href="https://github.blog/news-insights/product-news/announcing-git-large-file-storage-lfs/" target="_blank" rel="noopener noreffer ">Github</a> but it would be great to automate generating these COFFs during the main program&rsquo;s build process.</p>
<p>Most build systems should support defining and running custom commands which makes it possible to integrate this during the build process. Here are some basic examples using <a href="https://www.gnu.org/software/make/manual/make.html" target="_blank" rel="noopener noreffer ">make</a>, <a href="https://learn.microsoft.com/en-us/cpp/build/reference/nmake-reference" target="_blank" rel="noopener noreffer ">nmake</a>, <a href="https://cmake.org/" target="_blank" rel="noopener noreffer ">cmake</a> and <a href="https://mesonbuild.com/" target="_blank" rel="noopener noreffer ">meson</a> with the <a href="https://gist.github.com/MEhrn00/9615b92d9bfd3c85d6cba69edb31387d" target="_blank" rel="noopener noreffer ">bin2coff.py</a> script. These examples are for a basic project with a <code>main.c</code> source file and a <code>hello.txt</code> file that needs to be embedded. The <code>bin2coff.py</code> script is put in a separate <code>scripts/</code> directory at <code>scripts/bin2coff.py</code> to keep the root of the project more organized.</p>
<p>Makefile</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-Makefile" data-lang="Makefile"><span class="line"><span class="cl"><span class="nv">CC</span> <span class="o">=</span> x86_64-w64-mingw32-gcc
</span></span><span class="line"><span class="cl"><span class="nv">PYTHON</span> <span class="o">=</span> python3
</span></span><span class="line"><span class="cl"><span class="nv">BIN2COFF</span> <span class="o">=</span> scripts/bin2coff.py
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nf">.PHONY </span><span class="o">:</span> <span class="n">all</span> <span class="n">clean</span>
</span></span><span class="line"><span class="cl"><span class="nf">all </span><span class="o">:</span> <span class="n">main</span>.<span class="n">exe</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nf">clean</span><span class="o">:</span>
</span></span><span class="line"><span class="cl">	rm main.exe main.o hello.o
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nf">main.exe </span><span class="o">:</span> <span class="n">main</span>.<span class="n">o</span> <span class="n">hello</span>.<span class="n">o</span>
</span></span><span class="line"><span class="cl">	<span class="k">$(</span>CC<span class="k">)</span> <span class="k">$(</span>LDFLAGS<span class="k">)</span> <span class="k">$(</span>TARGET_ARCH<span class="k">)</span> $^ <span class="k">$(</span>LDLIBS<span class="k">)</span> -o <span class="nv">$@</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nf">hello.o </span><span class="o">:</span> <span class="n">hello</span>.<span class="n">txt</span>
</span></span><span class="line"><span class="cl">	<span class="k">$(</span>PYTHON<span class="k">)</span> <span class="k">$(</span>BIN2COFF<span class="k">)</span> -m amd64 $&lt; <span class="nv">$@</span>
</span></span></code></pre></div><p>NMake</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-makefile" data-lang="makefile"><span class="line"><span class="cl"><span class="nv">PYTHON</span> <span class="o">=</span> python3
</span></span><span class="line"><span class="cl"><span class="nv">BIN2COFF</span> <span class="o">=</span> .<span class="se">\s</span>cripts<span class="se">\b</span>in2coff.py
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nf">all </span><span class="o">:</span> <span class="n">main</span>.<span class="n">exe</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nf">clean</span><span class="o">:</span>
</span></span><span class="line"><span class="cl">	del /f main.exe main.obj hello.obj
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nf">main.exe </span><span class="o">:</span> <span class="n">main</span>.<span class="n">obj</span> <span class="n">hello</span>.<span class="n">obj</span>
</span></span><span class="line"><span class="cl">	<span class="k">$(</span>CC<span class="k">)</span> <span class="k">$(</span>CFLAGS<span class="k">)</span> /Fe:<span class="nv">$@</span> <span class="nv">$*</span>*
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nf">hello.obj </span><span class="o">:</span> <span class="n">hello</span>.<span class="n">txt</span>
</span></span><span class="line"><span class="cl">	<span class="k">$(</span>PYTHON<span class="k">)</span> <span class="k">$(</span>BIN2COFF<span class="k">)</span> <span class="nv">$?</span> <span class="nv">$@</span>
</span></span></code></pre></div><p>CMakeLists.txt</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cmake" data-lang="cmake"><span class="line"><span class="cl"><span class="nb">cmake_minimum_required</span><span class="p">(</span><span class="s">VERSION</span> <span class="s">3.18</span><span class="p">)</span><span class="err">
</span></span></span><span class="line"><span class="cl"><span class="err">
</span></span></span><span class="line"><span class="cl"><span class="err"></span><span class="nb">project</span><span class="p">(</span><span class="s">example</span> <span class="s">LANGUAGES</span> <span class="s">C</span><span class="p">)</span><span class="err">
</span></span></span><span class="line"><span class="cl"><span class="err">
</span></span></span><span class="line"><span class="cl"><span class="err"></span><span class="nb">find_package</span><span class="p">(</span><span class="s">Python</span> <span class="s">REQUIRED</span> <span class="s">COMPONENTS</span> <span class="s">Interpreter</span><span class="p">)</span><span class="err">
</span></span></span><span class="line"><span class="cl"><span class="err">
</span></span></span><span class="line"><span class="cl"><span class="err"></span><span class="nb">add_custom_command</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">  <span class="s">OUTPUT</span> <span class="s">hello.o</span>
</span></span><span class="line"><span class="cl">  <span class="s">COMMAND</span>
</span></span><span class="line"><span class="cl">    <span class="o">${</span><span class="nv">Python_EXECUTABLE</span><span class="o">}</span> <span class="o">${</span><span class="nv">CMAKE_CURRENT_SOURCE_DIR</span><span class="o">}</span><span class="s">/scripts/bin2coff.py</span>
</span></span><span class="line"><span class="cl">      <span class="o">${</span><span class="nv">CMAKE_CURRENT_SOURCE_DIR</span><span class="o">}</span><span class="s">/hello.txt</span>
</span></span><span class="line"><span class="cl">      <span class="s">hello.o</span>
</span></span><span class="line"><span class="cl">  <span class="s">DEPENDS</span> <span class="o">${</span><span class="nv">CMAKE_CURRENT_SOURCE_DIR</span><span class="o">}</span><span class="s">/hello.txt</span>
</span></span><span class="line"><span class="cl">  <span class="s">COMMENT</span> <span class="s2">&#34;Building hello.o from hello.txt with bin2coff.py&#34;</span>
</span></span><span class="line"><span class="cl">  <span class="s">VERBATIM</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span><span class="err">
</span></span></span><span class="line"><span class="cl"><span class="err">
</span></span></span><span class="line"><span class="cl"><span class="err"></span><span class="nb">add_custom_target</span><span class="p">(</span><span class="s">hello_gen</span> <span class="s">DEPENDS</span> <span class="s">hello.o</span><span class="p">)</span><span class="err">
</span></span></span><span class="line"><span class="cl"><span class="err">
</span></span></span><span class="line"><span class="cl"><span class="err"></span><span class="nb">add_library</span><span class="p">(</span><span class="s">hello</span> <span class="s">OBJECT</span> <span class="s">IMPORTED</span><span class="p">)</span><span class="err">
</span></span></span><span class="line"><span class="cl"><span class="err"></span><span class="nb">set_target_properties</span><span class="p">(</span><span class="s">hello</span> <span class="s">PROPERTIES</span>
</span></span><span class="line"><span class="cl">  <span class="s">IMPORTED_OBJECTS</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;${CMAKE_CURRENT_BINARY_DIR}/hello.o&#34;</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span><span class="err">
</span></span></span><span class="line"><span class="cl"><span class="err">
</span></span></span><span class="line"><span class="cl"><span class="err"></span><span class="nb">add_executable</span><span class="p">(</span><span class="s">main</span> <span class="s">main.c</span><span class="p">)</span><span class="err">
</span></span></span><span class="line"><span class="cl"><span class="err"></span><span class="nb">target_link_libraries</span><span class="p">(</span><span class="s">main</span> <span class="s">hello</span><span class="p">)</span><span class="err">
</span></span></span></code></pre></div><p>meson.build</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-meson" data-lang="meson"><span class="line"><span class="cl"><span class="nb">project</span><span class="p">(</span><span class="s">&#39;example&#39;</span><span class="p">,</span><span class="w"> </span><span class="s">&#39;c&#39;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="n">python</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">find_program</span><span class="p">(</span><span class="s">&#39;python3&#39;</span><span class="p">,</span><span class="w"> </span><span class="n">native</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="p">,</span><span class="w">  </span><span class="n">required</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="n">hello</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">custom_target</span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="s">&#39;hello&#39;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="n">output</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="s">&#39;hello.o&#39;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="n">input</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="s">&#39;hello.txt&#39;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="n">command</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="n">python</span><span class="p">,</span><span class="w"> </span><span class="s">&#39;@CURRENT_SOURCE_DIR@/scripts/bin2coff.py&#39;</span><span class="p">,</span><span class="w"> </span><span class="s">&#39;@INPUT@&#39;</span><span class="p">,</span><span class="w"> </span><span class="s">&#39;@OUTPUT@&#39;</span><span class="p">]</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nb">executable</span><span class="p">(</span><span class="s">&#39;main&#39;</span><span class="p">,</span><span class="w"> </span><span class="s">&#39;main.c&#39;</span><span class="p">,</span><span class="w"> </span><span class="n">hello</span><span class="p">)</span><span class="w">
</span></span></span></code></pre></div><h2 id="wrapping-up">Wrapping Up</h2>
<p>This post provides an alternative method for embedding file data in C/C++ without needing to store it as a large byte array in the source code. GNU <code>ld</code> is the standard linker on most Linux systems so this process works without needing to install any extra tools. Since COFFs are a relatively straightforward file format, it makes writing a custom tool that performs the same functionality a lot simpler to create.</p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>I do not know of any other linkers aside from GNU/MinGW <code>ld</code> and LLVM <code>lld</code> that are capable of outputting an object file with arbitrary binary data embedded inside it. There may be other ones I am unfamiliar with that can.&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:2">
<p>It may be possible to compile LLVM <code>lld</code> from source with COFF target support; however, I have not explored or tried it.&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></description></item><item><title>Writing Beacon Object Files Without DFR</title><link>https://blog.cybershenanigans.space/posts/writing-bofs-without-dfr/</link><pubDate>Mon, 18 Nov 2024 00:00:00 +0000</pubDate><author>Matt Ehrnschwender</author><guid>https://blog.cybershenanigans.space/posts/writing-bofs-without-dfr/</guid><description><![CDATA[<h2 id="intro">Intro</h2>
<p><a href="https://hstechdocs.helpsystems.com/manuals/cobaltstrike/current/userguide/content/topics/beacon-object-files_main.htm" target="_blank" rel="noopener noreffer ">Beacon Object Files</a> have become very popular for red teams to add additional capabilities on the fly without needing to include the overhead of a reflective DLL or .NET assembly. This advantage comes at the cost of Beacon Object Files being a little bit awkward to develop. One development quirk is the need to prefix imported symbols with the associated library name where the symbol can be found. This concept, known as <a href="https://hstechdocs.helpsystems.com/manuals/cobaltstrike/current/userguide/content/topics/beacon-object-files_dynamic-func-resolution.htm" target="_blank" rel="noopener noreffer ">Dynamic Function Resolution</a> (or DFR), is how the BOF tells the BOF loader where to find external symbols.</p>
<p>What if I told you that you do not need to write these DFR prototypes in your code when developing BOFs?</p>
<p></p>
<h2 id="tl-dr">TL; DR</h2>
<p><a href="https://www.man7.org/linux/man-pages/man1/objcopy.1.html" target="_blank" rel="noopener noreffer ">objcopy</a> supports redefining symbol names in object files using the <code>--redefine-sym</code> or <code>--redefine-syms</code> flag. This can be used to translate imported symbols from the normal system definition to the DFR format during post-processing.</p>
<h2 id="the-need-for-dfr">The Need For DFR</h2>
<p>An important thing to note about Beacon Object Files is that the resulting file a BOF loader loads is a generic <a href="https://en.wikipedia.org/wiki/COFF" target="_blank" rel="noopener noreffer ">COFF</a> file. This may seem rather obvious to people who have written BOFs before, but it is important to note because it helps identify what exactly a BOF loader has to work with and what data it lacks.</p>
<p>One piece of information that a COFF contains is a <a href="https://learn.microsoft.com/en-us/windows/win32/debug/pe-format#coff-symbol-table" target="_blank" rel="noopener noreffer ">symbol table</a>. This is an array of structures listing both the symbols that the COFF defines and the external symbols that the COFF requires. Each symbol definition includes the name of the symbol as is declared in the source file itself. What the symbol table lacks is the name of the external library where the symbol can be found. The linker&rsquo;s job is to take these symbols from the symbol table and search for them in a predefined set of libraries. Since BOFs do not go through a linking stage, this job is passed on to the BOF loader. Linkers will perform a brute-force style search to locate these symbols which is not the most ideal approach for a BOF loader.</p>
<p>This is where the DFR concept comes into play. Instead of performing this brute-force search every single time a BOF is loaded, the library names are instead integrated directly into the symbol name. The way this is done is by prefixing the symbol name with the library name and separating them with a dollar sign (<code>$</code>). For example, if a BOF requires the symbol <code>CreateFileA</code> and that symbol lives in <code>kernel32.dll</code>, the BOF would instead define the symbol <code>KERNEL32$CreateFileA</code> and the BOF loader will know to search for the <code>CreateFileA</code> symbol in <code>kernel32</code>.</p>
<h2 id="dfr-issues">DFR Issues</h2>
<p>This method of prepending the library name along with the symbol name works and has been the pretty standard way of defining imports in BOFs but there can be some issues with this approach.</p>
<h3 id="mismatched-prototypes">Mismatched Prototypes</h3>
<p>Since an already declared symbol needs to be redeclared using the DFR format, this manual redeclaration could potentially not match the original one exactly due to a typo. For basic functions, this error may be easy to find but for more complicated functions, it can be a little bit more difficult to identify.</p>
<p>Some functions in the Windows API are known to include a rather large number of parameters. Take <a href="https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-createprocesswithlogonw" target="_blank" rel="noopener noreffer ">CreateProcessWithLogonW</a> as an example. This is what the DFR declaration would look like in order to use this function in a BOF.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">DECLSPEC_IMPORT</span> <span class="n">BOOL</span> <span class="n">WINAPI</span> <span class="n">ADVAPI32</span><span class="err">$</span><span class="nf">CreateProcessWithLogonW</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">	<span class="n">LPCWSTR</span> <span class="n">lpUsername</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">	<span class="n">LPCWSTR</span> <span class="n">lpDomain</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">	<span class="n">LPCWSTR</span> <span class="n">lpPassword</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">	<span class="n">DWORD</span> <span class="n">dwLogonFlags</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">	<span class="n">LPCWSTR</span> <span class="n">lpApplicationName</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">	<span class="n">LPWSTR</span> <span class="n">lpCommandLine</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">	<span class="n">DWORD</span> <span class="n">dwCreationFlags</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">	<span class="n">LPVOID</span> <span class="n">lpEnvironment</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">	<span class="n">LPCWSTR</span> <span class="n">lpCurrentDirectory</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">	<span class="n">LPSTARTUPINFOW</span> <span class="n">lpStartupInfo</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">	<span class="n">LPPROCESS_INFORMATION</span> <span class="n">lpProcessInformation</span><span class="p">);</span>
</span></span></code></pre></div><p>If a parameter is swapped, omitted, or the type is wrong in the declaration, the function may not behave how it is expected to behave. The exact issue that occurs will depend on what part of the declaration is incorrect. In some cases, the function may work during one run but fail in another one. Like with many things related to C development, it just depends on how the computer is feeling at that moment in time if it is going to work or not ¯\_(ツ)_/¯.</p>
<p>Regardless of what error is returned when this type of issue occurs, this mistake can only be spotted by manually reviewing the code and double checking that the DFR prototype matches the original one exactly.</p>
<h4 id="c-the-savior">C++, the Savior</h4>
<p>In the <a href="https://www.cobaltstrike.com/blog/simplifying-bof-development" target="_blank" rel="noopener noreffer ">&ldquo;Simplifying BOF Development: Debug, Test, and Save Your B(e)acon&rdquo;</a> blog post by Fortra, <a href="https://x.com/HenriNurmi" target="_blank" rel="noopener noreffer ">Henri Nurmi</a> mentioned using the C++11 <a href="https://en.cppreference.com/w/cpp/language/decltype" target="_blank" rel="noopener noreffer ">decltype</a> specifier to help solve this issue.</p>
<p>This pattern is less error-prone since the new DFR symbol declaration is constructed directly from the original one.</p>
<p>The same <code>CreateProcessWithLogonW</code> prototype would look something like this using decltype.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">DECLSPEC_IMPORT</span> <span class="nf">decltype</span><span class="p">(</span><span class="n">CreateProcessWithLogonW</span><span class="p">)</span> <span class="n">ADVAPI32</span><span class="err">$</span><span class="n">CreateProcessWithLogonW</span><span class="p">;</span>
</span></span></code></pre></div><p>The original function prototype does not need to be manually rewritten since it is provided by decltype.</p>
<p>The caveat here is that you need a C++ compiler to compile the BOF so it requires dealing with some C++ specific nuances like <a href="https://learn.microsoft.com/en-us/cpp/build/reference/decorated-names?view=msvc-170" target="_blank" rel="noopener noreffer ">name mangling</a> but it does make declaring DFR prototypes a lot easier.</p>
<h3 id="executable-generation">Executable Generation</h3>
<p>During the testing phases of developing a BOF, it is helpful to compile the code into an executable or integrate it into a testing framework. Adding the DFR specification to imported symbols means that they will not be resolvable by the system linker. The system linker is unaware of the DFR format and interprets the <code>&lt;library&gt;$&lt;symbol&gt;</code> value as the symbol name itself.</p>
<p>There are some workarounds for this.</p>
<hr>
<p>Filename: <code>examplebof.c</code></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;windows.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;lmcons.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;beacon.h&#34;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="cl"><span class="n">DECLSPEC_IMPORT</span> <span class="n">DWORD</span> <span class="n">WINAPI</span> <span class="n">KERNEL32</span><span class="err">$</span><span class="nf">GetCurrentProcessId</span><span class="p">(</span><span class="kt">void</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="n">DECLSPEC_IMPORT</span> <span class="n">BOOL</span> <span class="n">WINAPI</span> <span class="n">ADVAPI32</span><span class="err">$</span><span class="nf">GetUserNameA</span><span class="p">(</span><span class="n">LPSTR</span><span class="p">,</span> <span class="n">LPDWORD</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">go</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">DWORD</span> <span class="n">pid</span> <span class="o">=</span> <span class="n">KERNEL32</span><span class="err">$</span><span class="nf">GetCurrentProcessId</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">    <span class="nf">BeaconPrintf</span><span class="p">(</span><span class="n">CALLBACK_OUTPUT</span><span class="p">,</span> <span class="s">&#34;Current process id: %lu&#34;</span><span class="p">,</span> <span class="n">pid</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="kt">char</span> <span class="n">username</span><span class="p">[</span><span class="n">UNLEN</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">0</span><span class="p">};</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="n">ADVAPI32</span><span class="err">$</span><span class="nf">GetUserNameA</span><span class="p">(</span><span class="n">username</span><span class="p">,</span> <span class="o">&amp;</span><span class="p">(</span><span class="n">DWORD</span><span class="p">){</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">username</span><span class="p">)</span> <span class="p">})</span> <span class="o">==</span> <span class="n">TRUE</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="nf">BeaconPrintf</span><span class="p">(</span><span class="n">CALLBACK_OUTPUT</span><span class="p">,</span> <span class="s">&#34;Username: %s&#34;</span><span class="p">,</span> <span class="n">username</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// Main function for building as an executable
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nf">go</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><hr>
<p>Attempting to compile this example BOF as an executable throws <code>undefined reference</code> errors when linking.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">matt@laptop :: ~/Documents/dev/writing-bofs-without-dfr-example &gt;&gt; x86_64-w64-mingw32-gcc -o examplebof.exe examplebof.c
</span></span><span class="line"><span class="cl">/usr/lib/gcc/x86_64-w64-mingw32/14.1.1/../../../../x86_64-w64-mingw32/bin/ld: /tmp/ccQizFTo.o:examplebof.c:<span class="o">(</span>.text+0x14<span class="o">)</span>: undefined reference to <span class="sb">`</span>__imp_KERNEL32<span class="nv">$GetCurrentProcessId</span><span class="s1">&#39;
</span></span></span><span class="line"><span class="cl"><span class="s1">/usr/lib/gcc/x86_64-w64-mingw32/14.1.1/../../../../x86_64-w64-mingw32/bin/ld: /tmp/ccQizFTo.o:examplebof.c:(.text+0x3b): undefined reference to `__imp_BeaconPrintf&#39;</span>
</span></span><span class="line"><span class="cl">/usr/lib/gcc/x86_64-w64-mingw32/14.1.1/../../../../x86_64-w64-mingw32/bin/ld: /tmp/ccQizFTo.o:examplebof.c:<span class="o">(</span>.text+0x73<span class="o">)</span>: undefined reference to <span class="sb">`</span>__imp_ADVAPI32<span class="nv">$GetUserNameA</span><span class="s1">&#39;
</span></span></span><span class="line"><span class="cl"><span class="s1">/usr/lib/gcc/x86_64-w64-mingw32/14.1.1/../../../../x86_64-w64-mingw32/bin/ld: /tmp/ccQizFTo.o:examplebof.c:(.text+0x97): undefined reference to `__imp_BeaconPrintf&#39;</span>
</span></span><span class="line"><span class="cl">collect2: error: ld returned <span class="m">1</span> <span class="nb">exit</span> status
</span></span><span class="line"><span class="cl">matt@laptop :: ~/Documents/dev/writing-bofs-without-dfr-example <span class="m">1</span> &gt;&gt;
</span></span></code></pre></div><p>A common way of fixing this issue is by wrapping all of the DFR prototypes in an <code>#ifdef</code> macro and choosing which version of the symbol to use depending on if that macro is defined or not. The DFR symbol and the system symbol can be aliased to a common name in order to refer to the different variants based on the configuration.</p>
<hr>
<p>Filename: <code>examplebof.c</code></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;windows.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;lmcons.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;beacon.h&#34;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="cl"><span class="cp">#ifdef BOF
</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="c1">// Use DFR if `BOF` is defined
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>
</span></span><span class="line"><span class="cl"><span class="n">DECLSPEC_IMPORT</span> <span class="n">DWORD</span> <span class="n">WINAPI</span> <span class="n">KERNEL32</span><span class="err">$</span><span class="nf">GetCurrentProcessId</span><span class="p">(</span><span class="kt">void</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="cp">#define kernel32_GetCurrentProcessId KERNEL32$GetCurrentProcessId
</span></span></span><span class="line"><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="cl"><span class="n">DECLSPEC_IMPORT</span> <span class="n">BOOL</span> <span class="n">WINAPI</span> <span class="n">ADVAPI32</span><span class="err">$</span><span class="nf">GetUserNameA</span><span class="p">(</span><span class="n">LPSTR</span><span class="p">,</span> <span class="n">LPDWORD</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="cp">#define advapi32_GetUserNameA ADVAPI32$GetUserNameA
</span></span></span><span class="line"><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="cl"><span class="cp">#else </span><span class="c1">// BOF
</span></span></span><span class="line"><span class="cl"><span class="c1">// Do not use DFR if `BOF` is not defined
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>
</span></span><span class="line"><span class="cl"><span class="cp">#define kernel32_GetCurrentProcessId GetCurrentProcessId
</span></span></span><span class="line"><span class="cl"><span class="cp">#define advapi32_GetUserNameA GetUserNameA
</span></span></span><span class="line"><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="cl"><span class="cp">#endif </span><span class="c1">// BOF
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>
</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">go</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">DWORD</span> <span class="n">pid</span> <span class="o">=</span> <span class="nf">kernel32_GetCurrentProcessId</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">    <span class="nf">BeaconPrintf</span><span class="p">(</span><span class="n">CALLBACK_OUTPUT</span><span class="p">,</span> <span class="s">&#34;Current process id: %lu&#34;</span><span class="p">,</span> <span class="n">pid</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="kt">char</span> <span class="n">username</span><span class="p">[</span><span class="n">UNLEN</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">0</span><span class="p">};</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="nf">advapi32_GetUserNameA</span><span class="p">(</span><span class="n">username</span><span class="p">,</span> <span class="o">&amp;</span><span class="p">(</span><span class="n">DWORD</span><span class="p">){</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">username</span><span class="p">)</span> <span class="p">})</span> <span class="o">==</span> <span class="n">TRUE</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="nf">BeaconPrintf</span><span class="p">(</span><span class="n">CALLBACK_OUTPUT</span><span class="p">,</span> <span class="s">&#34;Username: %s&#34;</span><span class="p">,</span> <span class="n">username</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="cp">#ifndef BOF
</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="c1">// Create a main function to wrap the BOF entrypoint
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nf">go</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="cp">#endif </span><span class="c1">// BOF
</span></span></span></code></pre></div><hr>
<p>Passing in the <code>-DBOF</code> flag during compilation will use the DFR import declarations and omitting that flag will use the normal system declarations. Both of the symbols are aliased with <code>&lt;libname&gt;_&lt;symbol&gt;</code> so that the correct symbol is used when referring to them.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># For compiling with the BOF DFR imports</span>
</span></span><span class="line"><span class="cl">x86_64-w64-mingw32-gcc -DBOF -c -o examplebof.o examplebof.c
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># For compiling the executable with the normal system imports</span>
</span></span><span class="line"><span class="cl">x86_64-w64-mingw32-gcc -o examplebof.exe examplebof.c
</span></span></code></pre></div><p>Compiling it with a Makefile</p>
<hr>
<p>Filename: <code>Makefile</code></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-Makefile" data-lang="Makefile"><span class="line"><span class="cl"><span class="nv">CC</span> <span class="o">=</span> x86_64-w64-mingw32-gcc
</span></span><span class="line"><span class="cl"><span class="nv">RM</span> <span class="o">=</span> rm -vf
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nv">sources</span> <span class="o">:=</span> examplebof.c
</span></span><span class="line"><span class="cl"><span class="nv">objs</span> <span class="o">:=</span> <span class="k">$(</span>sources:.c<span class="o">=</span>.o<span class="k">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nf">.PHONY</span><span class="o">:</span> <span class="n">all</span> <span class="n">clean</span>
</span></span><span class="line"><span class="cl"><span class="nf">all </span><span class="o">:</span> <span class="n">examplebof</span>.<span class="n">bof</span>.<span class="n">o</span> <span class="n">examplebof</span>.<span class="n">exe</span>
</span></span><span class="line"><span class="cl"><span class="nf">clean</span><span class="o">:</span>
</span></span><span class="line"><span class="cl">	<span class="k">$(</span>RM<span class="k">)</span> examplebof.bof.o examplebof.exe <span class="k">$(</span>objs<span class="k">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nf">examplebof.o </span><span class="o">:</span> <span class="n">examplebof</span>.<span class="n">c</span> <span class="n">beacon</span>.<span class="n">h</span>
</span></span><span class="line"><span class="cl"><span class="nf">examplebof.bof.o </span><span class="o">:</span> <span class="n">examplebof</span>.<span class="n">c</span> <span class="n">beacon</span>.<span class="n">h</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nf">%.bof.o </span><span class="o">:</span> %.<span class="n">c</span>
</span></span><span class="line"><span class="cl">	<span class="k">$(</span>CC<span class="k">)</span> -DBOF <span class="k">$(</span>CFLAGS<span class="k">)</span> <span class="k">$(</span>TARGET_ARCH<span class="k">)</span> -c <span class="k">$(</span>OUTPUT_OPTION<span class="k">)</span> $&lt;
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nf">% </span><span class="o">:</span> %.<span class="n">o</span>
</span></span><span class="line"><span class="cl"><span class="nf">%.exe </span><span class="o">:</span> %.<span class="n">o</span>
</span></span><span class="line"><span class="cl">	<span class="k">$(</span>LINK.o<span class="k">)</span> $^ <span class="k">$(</span>LDLIBS<span class="k">)</span> -o <span class="nv">$@</span>
</span></span></code></pre></div><hr>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">matt@laptop :: ~/Documents/dev/writing-bofs-without-dfr-example &gt;&gt; make
</span></span><span class="line"><span class="cl">x86_64-w64-mingw32-gcc -DBOF   -c -o examplebof.bof.o examplebof.c
</span></span><span class="line"><span class="cl">x86_64-w64-mingw32-gcc    -c -o examplebof.o examplebof.c
</span></span><span class="line"><span class="cl">x86_64-w64-mingw32-gcc   examplebof.o  -o examplebof.exe
</span></span><span class="line"><span class="cl">/usr/lib/gcc/x86_64-w64-mingw32/14.1.1/../../../../x86_64-w64-mingw32/bin/ld: examplebof.o:examplebof.c:<span class="o">(</span>.text+0x3b<span class="o">)</span>: undefined reference to <span class="sb">`</span>__imp_BeaconPrintf<span class="s1">&#39;
</span></span></span><span class="line"><span class="cl"><span class="s1">/usr/lib/gcc/x86_64-w64-mingw32/14.1.1/../../../../x86_64-w64-mingw32/bin/ld: examplebof.o:examplebof.c:(.text+0x97): undefined reference to `__imp_BeaconPrintf&#39;</span>
</span></span><span class="line"><span class="cl">collect2: error: ld returned <span class="m">1</span> <span class="nb">exit</span> status
</span></span><span class="line"><span class="cl">make: *** <span class="o">[</span>Makefile:20: examplebof.exe<span class="o">]</span> Error <span class="m">1</span>
</span></span><span class="line"><span class="cl">matt@laptop :: ~/Documents/dev/writing-bofs-without-dfr-example <span class="m">2</span> &gt;&gt;
</span></span></code></pre></div><p>The BOF version compiles successfully; however, the executable version still yields a few <code>undefined reference</code> linking errors.</p>
<p>The linker is failing to find the Beacon API (BeaconPrintf) symbols. These symbols typically reside in a BOF loader and are resolved during the loading process so they do not live anywhere on the system for the linker to find.</p>
<p>A workaround for this issue is to create mock implementations of the Beacon API and link them in when compiling the executable version. The provided Visual Studio BOF template mentioned in the <a href="https://www.cobaltstrike.com/blog/simplifying-bof-development" target="_blank" rel="noopener noreffer ">&ldquo;Simplifying BOF Development: Debug, Test, and Save Your B(e)acon&rdquo;</a> blog post uses this strategy (<a href="https://github.com/Cobalt-Strike/bof-vs/blob/855a33afacd6efad3eaceebe42c5ece4a435d91d/BOF-Template/base/mock.cpp#L391" target="_blank" rel="noopener noreffer ">Cobalt-Strike/bof-vs/BOF-template/base/mock.cpp#L391</a>).</p>
<p>The mock Beacon API implementations can be ported over in a way that works with this BOF. Ideally, these would be implemented in a static library that can be reused across different projects but since <code>BeaconPrintf</code> is the only function needed for this project, it is fine to just include it along with the BOF.</p>
<hr>
<p>Filename: <code>beacon_mock.c</code></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;beacon_mock.h&#34;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;assert.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdarg.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="cl"><span class="c1">/// BeaconPrintf implementation for printing to stdout.
</span></span></span><span class="line"><span class="cl"><span class="c1">/// Based off of https://github.com/Cobalt-Strike/bof-vs/blob/855a33afacd6efad3eaceebe42c5ece4a435d91d/BOF-Template/base/mock.cpp#L391 but ported to C
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kt">void</span> <span class="nf">BeaconPrintf</span><span class="p">(</span><span class="kt">int</span> <span class="n">type</span><span class="p">,</span> <span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">fmt</span><span class="p">,</span> <span class="p">...)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">	<span class="nf">printf</span><span class="p">(</span><span class="s">&#34;[Output Callback: (0x%02x)]: &#34;</span><span class="p">,</span> <span class="n">type</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">	<span class="n">va_list</span> <span class="n">args</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">	<span class="nf">va_start</span><span class="p">(</span><span class="n">args</span><span class="p">,</span> <span class="n">fmt</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">	<span class="nf">vprintf</span><span class="p">(</span><span class="n">fmt</span><span class="p">,</span> <span class="n">args</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">	<span class="nf">puts</span><span class="p">(</span><span class="s">&#34;&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">	<span class="nf">assert</span><span class="p">(</span><span class="nf">fflush</span><span class="p">(</span><span class="n">stdout</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">	<span class="nf">va_end</span><span class="p">(</span><span class="n">args</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><hr>
<p>Filename: <code>beacon_mock.h</code></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#ifndef BEACON_MOCK_H
</span></span></span><span class="line"><span class="cl"><span class="cp">#define BEACON_MOCK_H
</span></span></span><span class="line"><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="cl"><span class="cp">#define CALLBACK_OUTPUT      0x0
</span></span></span><span class="line"><span class="cl"><span class="cp">#define CALLBACK_OUTPUT_OEM  0x1e
</span></span></span><span class="line"><span class="cl"><span class="cp">#define CALLBACK_OUTPUT_UTF8 0x20
</span></span></span><span class="line"><span class="cl"><span class="cp">#define CALLBACK_ERROR       0x0d
</span></span></span><span class="line"><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">BeaconPrintf</span><span class="p">(</span><span class="kt">int</span> <span class="n">type</span><span class="p">,</span> <span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">fmt</span><span class="p">,</span> <span class="p">...);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="cp">#endif </span><span class="c1">// BEACON_MOCK_H
</span></span></span></code></pre></div><hr>
<p>Filename: <code>examplebof.c</code></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;windows.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;lmcons.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="cl"><span class="cp">#ifdef BOF
</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="c1">// Include the regular beacon.h definitions when compiling as a BOF
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="cp">#include</span> <span class="cpf">&#34;beacon.h&#34;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="cl"><span class="n">DECLSPEC_IMPORT</span> <span class="n">DWORD</span> <span class="n">WINAPI</span> <span class="n">KERNEL32</span><span class="err">$</span><span class="nf">GetCurrentProcessId</span><span class="p">(</span><span class="kt">void</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="cp">#define kernel32_GetCurrentProcessId KERNEL32$GetCurrentProcessId
</span></span></span><span class="line"><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="cl"><span class="n">DECLSPEC_IMPORT</span> <span class="n">BOOL</span> <span class="n">WINAPI</span> <span class="n">ADVAPI32</span><span class="err">$</span><span class="nf">GetUserNameA</span><span class="p">(</span><span class="n">LPSTR</span><span class="p">,</span> <span class="n">LPDWORD</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="cp">#define advapi32_GetUserNameA ADVAPI32$GetUserNameA
</span></span></span><span class="line"><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="cl"><span class="cp">#else </span><span class="c1">// BOF
</span></span></span><span class="line"><span class="cl"><span class="c1">// Include the mock Beacon API definitions when compiling as a standalone executable
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="cp">#include</span> <span class="cpf">&#34;beacon_mock.h&#34;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="cl"><span class="cp">#define kernel32_GetCurrentProcessId GetCurrentProcessId
</span></span></span><span class="line"><span class="cl"><span class="cp">#define advapi32_GetUserNameA GetUserNameA
</span></span></span><span class="line"><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="cl"><span class="cp">#endif </span><span class="c1">// BOF
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>
</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">go</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">DWORD</span> <span class="n">pid</span> <span class="o">=</span> <span class="nf">kernel32_GetCurrentProcessId</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">    <span class="nf">BeaconPrintf</span><span class="p">(</span><span class="n">CALLBACK_OUTPUT</span><span class="p">,</span> <span class="s">&#34;Current process id: %lu&#34;</span><span class="p">,</span> <span class="n">pid</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="kt">char</span> <span class="n">username</span><span class="p">[</span><span class="n">UNLEN</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">0</span><span class="p">};</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="nf">advapi32_GetUserNameA</span><span class="p">(</span><span class="n">username</span><span class="p">,</span> <span class="o">&amp;</span><span class="p">(</span><span class="n">DWORD</span><span class="p">){</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">username</span><span class="p">)</span> <span class="p">})</span> <span class="o">==</span> <span class="n">TRUE</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="nf">BeaconPrintf</span><span class="p">(</span><span class="n">CALLBACK_OUTPUT</span><span class="p">,</span> <span class="s">&#34;Username: %s&#34;</span><span class="p">,</span> <span class="n">username</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="cp">#ifndef BOF
</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="c1">// Create a main function to wrap the BOF entrypoint
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nf">go</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="cp">#endif </span><span class="c1">// BOF
</span></span></span></code></pre></div><hr>
<p>And adjusting the Makefile above to include the new mock Beacon API implementations</p>
<hr>
<p>Filename: <code>Makefile</code></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-Makefile" data-lang="Makefile"><span class="line"><span class="cl"><span class="nv">CC</span> <span class="o">=</span> x86_64-w64-mingw32-gcc
</span></span><span class="line"><span class="cl"><span class="nv">RM</span> <span class="o">=</span> rm -vf
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nv">sources</span> <span class="o">:=</span> examplebof.c beacon_mock.c
</span></span><span class="line"><span class="cl"><span class="nv">objs</span> <span class="o">:=</span> <span class="k">$(</span>sources:.c<span class="o">=</span>.o<span class="k">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nf">.PHONY</span><span class="o">:</span> <span class="n">all</span> <span class="n">clean</span>
</span></span><span class="line"><span class="cl"><span class="nf">all </span><span class="o">:</span> <span class="n">examplebof</span>.<span class="n">bof</span>.<span class="n">o</span> <span class="n">examplebof</span>.<span class="n">exe</span>
</span></span><span class="line"><span class="cl"><span class="nf">clean</span><span class="o">:</span>
</span></span><span class="line"><span class="cl">	<span class="k">$(</span>RM<span class="k">)</span> examplebof.bof.o examplebof.exe <span class="k">$(</span>objs<span class="k">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nf">examplebof.exe </span><span class="o">:</span> <span class="n">examplebof</span>.<span class="n">o</span> <span class="n">beacon_mock</span>.<span class="n">o</span>
</span></span><span class="line"><span class="cl"><span class="nf">examplebof.bof.o </span><span class="o">:</span> <span class="n">examplebof</span>.<span class="n">c</span> <span class="n">beacon</span>.<span class="n">h</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nf">examplebof.o </span><span class="o">:</span> <span class="n">examplebof</span>.<span class="n">c</span> <span class="n">beacon_mock</span>.<span class="n">h</span>
</span></span><span class="line"><span class="cl"><span class="nf">beacon_mock.o </span><span class="o">:</span> <span class="n">beacon_mock</span>.<span class="n">c</span> <span class="n">beacon_mock</span>.<span class="n">h</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nf">%.bof.o </span><span class="o">:</span> %.<span class="n">c</span>
</span></span><span class="line"><span class="cl">	<span class="k">$(</span>CC<span class="k">)</span> -DBOF <span class="k">$(</span>CFLAGS<span class="k">)</span> <span class="k">$(</span>TARGET_ARCH<span class="k">)</span> -c <span class="k">$(</span>OUTPUT_OPTION<span class="k">)</span> $&lt;
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nf">% </span><span class="o">:</span> %.<span class="n">o</span>
</span></span><span class="line"><span class="cl"><span class="nf">%.exe </span><span class="o">:</span> %.<span class="n">o</span>
</span></span><span class="line"><span class="cl">	<span class="k">$(</span>LINK.o<span class="k">)</span> $^ <span class="k">$(</span>LDLIBS<span class="k">)</span> -o <span class="nv">$@</span>
</span></span></code></pre></div><hr>
<p>Compiling this as both a BOF and a standalone executable should work now since there is an implementation for <code>BeaconPrintf</code> present that the linker can find.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">matt@laptop :: ~/Documents/dev/writing-bofs-without-dfr-example &gt;&gt; ls
</span></span><span class="line"><span class="cl">beacon.h  beacon_mock.c  beacon_mock.h  examplebof.c  Makefile
</span></span><span class="line"><span class="cl">matt@laptop :: ~/Documents/dev/writing-bofs-without-dfr-example &gt;&gt; make
</span></span><span class="line"><span class="cl">x86_64-w64-mingw32-gcc -DBOF   -c -o examplebof.bof.o examplebof.c
</span></span><span class="line"><span class="cl">x86_64-w64-mingw32-gcc    -c -o examplebof.o examplebof.c
</span></span><span class="line"><span class="cl">x86_64-w64-mingw32-gcc    -c -o beacon_mock.o beacon_mock.c
</span></span><span class="line"><span class="cl">x86_64-w64-mingw32-gcc   examplebof.o beacon_mock.o  -o examplebof.exe
</span></span><span class="line"><span class="cl">matt@laptop :: ~/Documents/dev/writing-bofs-without-dfr-example &gt;&gt; ls
</span></span><span class="line"><span class="cl">beacon.h  beacon_mock.c  beacon_mock.h  beacon_mock.o  examplebof.bof.o  examplebof.c  examplebof.exe  examplebof.o  Makefile
</span></span><span class="line"><span class="cl">matt@laptop :: ~/Documents/dev/writing-bofs-without-dfr-example &gt;&gt; wine ./examplebof.exe
</span></span><span class="line"><span class="cl">002c:fixme:winediag:loader_init wine-staging 9.15 is a testing version containing experimental patches.
</span></span><span class="line"><span class="cl">002c:fixme:winediag:loader_init Please mention your exact version when filing bug reports on winehq.org.
</span></span><span class="line"><span class="cl"><span class="o">[</span>Output Callback: <span class="o">(</span>0x00<span class="o">)]</span>: Current process id: <span class="m">32</span>
</span></span><span class="line"><span class="cl"><span class="o">[</span>Output Callback: <span class="o">(</span>0x00<span class="o">)]</span>: Username: matt
</span></span><span class="line"><span class="cl">matt@laptop :: ~/Documents/dev/writing-bofs-without-dfr-example &gt;&gt;
</span></span></code></pre></div><h2 id="symbol-redefining-with-objcopy">Symbol Redefining With Objcopy</h2>
<p>As seen above, this method for managing DFR imports can be a little bit of a hassle. It requires various macros and other helpers in the source code causing a lot of clutter. It would be nice if there was a way to write a BOF like a normal C program but manage the DFR aspects separately outside of the source code.</p>
<p>This is possible using something like <a href="https://www.man7.org/linux/man-pages/man1/objcopy.1.html" target="_blank" rel="noopener noreffer ">objcopy</a>.</p>
<p>Objcopy is a tool from the <a href="https://www.gnu.org/software/binutils/" target="_blank" rel="noopener noreffer ">GNU Binutils</a> designed to manipulate object files. The Binutils have been around for over two decades and are pretty common on most Linux systems. Objcopy supports various different object file formats including COFFs.</p>
<p>One feature that objcopy includes is the ability to rename symbols using the <code>--redefine-sym</code> flag. This allows changing the name of a symbol in an existing object file.</p>
<p>Here is how this can be utilized with Beacon Object Files.</p>
<p>The example BOF code above can be rewritten to remove all of the DFR specifics.</p>
<hr>
<p>Filename: <code>examplebof.c</code></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;windows.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;lmcons.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;beacon.h&#34;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">go</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">DWORD</span> <span class="n">pid</span> <span class="o">=</span> <span class="nf">GetCurrentProcessId</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">    <span class="nf">BeaconPrintf</span><span class="p">(</span><span class="n">CALLBACK_OUTPUT</span><span class="p">,</span> <span class="s">&#34;Current process id: %lu&#34;</span><span class="p">,</span> <span class="n">pid</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="kt">char</span> <span class="n">username</span><span class="p">[</span><span class="n">UNLEN</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">0</span><span class="p">};</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="nf">GetUserNameA</span><span class="p">(</span><span class="n">username</span><span class="p">,</span> <span class="o">&amp;</span><span class="p">(</span><span class="n">DWORD</span><span class="p">){</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">username</span><span class="p">)</span> <span class="p">})</span> <span class="o">==</span> <span class="n">TRUE</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="nf">BeaconPrintf</span><span class="p">(</span><span class="n">CALLBACK_OUTPUT</span><span class="p">,</span> <span class="s">&#34;Username: %s&#34;</span><span class="p">,</span> <span class="n">username</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><hr>
<p>Compiling this version of the example BOF and using it with <a href="https://github.com/trustedsec/COFFLoader" target="_blank" rel="noopener noreffer ">TrustedSec&rsquo;s COFFLoader</a> will fail.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="cl"><span class="nb">PS </span><span class="n">C:</span><span class="p">\</span><span class="n">Users</span><span class="p">\</span><span class="n">User</span><span class="p">\</span><span class="n">Documents</span><span class="p">\</span><span class="nb">writing-bofs</span><span class="n">-without-dfr-example</span><span class="p">&gt;</span> <span class="p">.\</span><span class="n">COFFLoader</span><span class="p">.</span><span class="py">exe</span> <span class="n">go</span> <span class="p">.\</span><span class="n">examplebof</span><span class="p">.</span><span class="py">bof</span><span class="p">.</span><span class="py">o</span>
</span></span><span class="line"><span class="cl"><span class="n">Got</span> <span class="n">contents</span> <span class="n">of</span> <span class="n">COFF</span> <span class="n">file</span>
</span></span><span class="line"><span class="cl"><span class="n">Running</span><span class="p">/</span><span class="n">Parsing</span> <span class="n">the</span> <span class="n">COFF</span> <span class="n">file</span>
</span></span><span class="line"><span class="cl"><span class="n">Machine</span> <span class="n">0x8664</span>
</span></span><span class="line"><span class="cl"><span class="n">Number</span> <span class="n">of</span> <span class="n">sections</span><span class="err">:</span> <span class="mf">7</span>
</span></span><span class="line"><span class="cl"><span class="n">TimeDateStamp</span> <span class="err">:</span> <span class="mf">0</span>
</span></span><span class="line"><span class="cl"><span class="n">PointerToSymbolTable</span> <span class="err">:</span> <span class="n">0x2C2</span>
</span></span><span class="line"><span class="cl"><span class="n">NumberOfSymbols</span><span class="err">:</span> <span class="mf">21</span>
</span></span><span class="line"><span class="cl"><span class="n">OptionalHeaderSize</span><span class="err">:</span> <span class="mf">0</span>
</span></span><span class="line"><span class="cl"><span class="n">Characteristics</span><span class="err">:</span> <span class="mf">4</span>
</span></span><span class="line"><span class="cl"><span class="p">...</span>
</span></span><span class="line"><span class="cl"><span class="n">Doing</span> <span class="n">Relocations</span> <span class="n">of</span> <span class="n">section</span><span class="err">:</span> <span class="mf">0</span>
</span></span><span class="line"><span class="cl">        <span class="n">VirtualAddress</span><span class="err">:</span> <span class="n">0x14</span>
</span></span><span class="line"><span class="cl">        <span class="n">SymbolTableIndex</span><span class="err">:</span> <span class="n">0x12</span>
</span></span><span class="line"><span class="cl">        <span class="n">Type</span><span class="err">:</span> <span class="n">0x4</span>
</span></span><span class="line"><span class="cl">        <span class="n">SymPtr</span><span class="err">:</span> <span class="n">0x1A</span>
</span></span><span class="line"><span class="cl">        <span class="n">SymVal</span><span class="err">:</span> <span class="n">__imp_GetCurrentProcessId</span>
</span></span><span class="line"><span class="cl">        <span class="n">SectionNumber</span><span class="err">:</span> <span class="n">0x0</span>
</span></span><span class="line"><span class="cl"><span class="n">Failed</span> <span class="n">to</span> <span class="n">resolve</span> <span class="n">symbol</span>
</span></span><span class="line"><span class="cl"><span class="n">Returning</span>
</span></span><span class="line"><span class="cl"><span class="n">Failed</span> <span class="n">to</span> <span class="n">run</span><span class="p">/</span><span class="n">parse</span> <span class="n">the</span> <span class="n">COFF</span> <span class="n">file</span>
</span></span><span class="line"><span class="cl"><span class="nb">PS </span><span class="n">C:</span><span class="p">\</span><span class="n">Users</span><span class="p">\</span><span class="n">User</span><span class="p">\</span><span class="n">Documents</span><span class="p">\</span><span class="nb">writing-bofs</span><span class="n">-without-dfr-example</span><span class="p">&gt;</span>
</span></span></code></pre></div><p>COFFLoader throws an error during the processing of the <code>__imp_GetCurrentProcessId</code> symbol because it is unable to parse out the library name.</p>
<p>Using objcopy, the imported symbols in the example BOF can be rewritten to match the DFR format. This is what the BOF loader expects to see when resolving these imported symbols.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">objcopy <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>	--redefine-sym <span class="s1">&#39;__imp_GetCurrentProcessId=__imp_KERNEL32$GetCurrentProcessId&#39;</span> <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>	--redefine-sym <span class="s1">&#39;__imp_GetUserNameA=__imp_ADVAPI32$GetUserNameA&#39;</span> <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>	examplebof.bof.o examplebof-redefined.bof.o
</span></span></code></pre></div><p><a href="https://book.rada.re/tools/rabin2/intro.html" target="_blank" rel="noopener noreffer ">Rabin2</a> can be used to verify that the symbols were renamed properly.</p>
<hr>
<p>File: <code>examplebof.bof.o</code></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">matt@laptop :: ~/Documents/dev/writing-bofs-without-dfr-example &gt;&gt; rabin2 -s examplebof.bof.o
</span></span><span class="line"><span class="cl"><span class="o">[</span>Symbols<span class="o">]</span>
</span></span><span class="line"><span class="cl">nth paddr      vaddr      <span class="nb">bind</span>   <span class="nb">type</span> size lib name                          demangled
</span></span><span class="line"><span class="cl">――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
</span></span><span class="line"><span class="cl"><span class="m">0</span>   0x00000000 0x00000000 LOCAL  FILE <span class="m">4</span>        .file
</span></span><span class="line"><span class="cl"><span class="m">0</span>   0x0000012c 0x00000000 GLOBAL FUNC <span class="m">4</span>        go
</span></span><span class="line"><span class="cl"><span class="m">0</span>   0x0000012c 0x00000000 LOCAL  SECT <span class="m">4</span>        .text
</span></span><span class="line"><span class="cl"><span class="m">0</span>   0x00000000 0x000000b0 LOCAL  SECT <span class="m">4</span>        .data
</span></span><span class="line"><span class="cl"><span class="m">0</span>   0x00000000 0x000000c0 LOCAL  SECT <span class="m">4</span>        .bss
</span></span><span class="line"><span class="cl"><span class="m">0</span>   0x000001dc 0x000000d0 LOCAL  SECT <span class="m">4</span>        .rdata
</span></span><span class="line"><span class="cl"><span class="m">0</span>   0x0000020c 0x00000100 LOCAL  SECT <span class="m">4</span>        .xdata
</span></span><span class="line"><span class="cl"><span class="m">0</span>   0x0000021c 0x00000110 LOCAL  SECT <span class="m">4</span>        .pdata
</span></span><span class="line"><span class="cl"><span class="m">0</span>   0x00000228 0x00000120 LOCAL  UNK  <span class="m">4</span>        .rdata<span class="nv">$zzz</span>
</span></span><span class="line"><span class="cl"><span class="m">0</span>   ---------- ---------- NONE   UNK  <span class="m">4</span>        imp.__imp_GetCurrentProcessId
</span></span><span class="line"><span class="cl"><span class="m">0</span>   ---------- ---------- NONE   UNK  <span class="m">4</span>        imp.__imp_BeaconPrintf
</span></span><span class="line"><span class="cl"><span class="m">0</span>   ---------- ---------- NONE   UNK  <span class="m">4</span>        imp.__imp_GetUserNameA
</span></span></code></pre></div><hr>
<p>File: <code>examplebof-redefined.bof.o</code></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">matt@laptop :: ~/Documents/dev/writing-bofs-without-dfr-example &gt;&gt; rabin2 -s example-redefined.bof.o
</span></span><span class="line"><span class="cl"><span class="o">[</span>Symbols<span class="o">]</span>
</span></span><span class="line"><span class="cl">nth paddr      vaddr      <span class="nb">bind</span>   <span class="nb">type</span> size lib name                                   demangled
</span></span><span class="line"><span class="cl">―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
</span></span><span class="line"><span class="cl"><span class="m">0</span>   0x00000000 0x00000000 LOCAL  FILE <span class="m">4</span>        .file
</span></span><span class="line"><span class="cl"><span class="m">0</span>   0x0000012c 0x00000000 GLOBAL FUNC <span class="m">4</span>        go
</span></span><span class="line"><span class="cl"><span class="m">0</span>   0x0000012c 0x00000000 LOCAL  SECT <span class="m">4</span>        .text
</span></span><span class="line"><span class="cl"><span class="m">0</span>   0x00000000 0x000000b0 LOCAL  SECT <span class="m">4</span>        .data
</span></span><span class="line"><span class="cl"><span class="m">0</span>   0x00000000 0x000000c0 LOCAL  SECT <span class="m">4</span>        .bss
</span></span><span class="line"><span class="cl"><span class="m">0</span>   0x000001dc 0x000000d0 LOCAL  SECT <span class="m">4</span>        .rdata
</span></span><span class="line"><span class="cl"><span class="m">0</span>   0x0000020c 0x00000100 LOCAL  SECT <span class="m">4</span>        .xdata
</span></span><span class="line"><span class="cl"><span class="m">0</span>   0x0000021c 0x00000110 LOCAL  SECT <span class="m">4</span>        .pdata
</span></span><span class="line"><span class="cl"><span class="m">0</span>   0x00000228 0x00000120 LOCAL  UNK  <span class="m">4</span>        .rdata<span class="nv">$zzz</span>
</span></span><span class="line"><span class="cl"><span class="m">0</span>   ---------- ---------- NONE   UNK  <span class="m">4</span>        imp.__imp_KERNEL32<span class="nv">$GetCurrentProcessId</span>
</span></span><span class="line"><span class="cl"><span class="m">0</span>   ---------- ---------- NONE   UNK  <span class="m">4</span>        imp.__imp_BeaconPrintf
</span></span><span class="line"><span class="cl"><span class="m">0</span>   ---------- ---------- NONE   UNK  <span class="m">4</span>        imp.__imp_ADVAPI32<span class="nv">$GetUserNameA</span>
</span></span></code></pre></div><hr>
<p>Testing the newly generated BOF with the redefined symbols now works with COFFLoader</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="cl"><span class="nb">PS </span><span class="n">C:</span><span class="p">\</span><span class="n">Users</span><span class="p">\</span><span class="n">User</span><span class="p">\</span><span class="n">Documents</span><span class="p">\</span><span class="nb">writing-bofs</span><span class="n">-without-dfr-example</span><span class="p">&gt;</span> <span class="p">.\</span><span class="n">COFFLoader</span><span class="p">.</span><span class="py">exe</span> <span class="n">go</span> <span class="p">.\</span><span class="nb">example-redefined</span><span class="p">.</span><span class="py">bof</span><span class="p">.</span><span class="py">o</span>
</span></span><span class="line"><span class="cl"><span class="n">Got</span> <span class="n">contents</span> <span class="n">of</span> <span class="n">COFF</span> <span class="n">file</span>
</span></span><span class="line"><span class="cl"><span class="n">Running</span><span class="p">/</span><span class="n">Parsing</span> <span class="n">the</span> <span class="n">COFF</span> <span class="n">file</span>
</span></span><span class="line"><span class="cl"><span class="n">Machine</span> <span class="n">0x8664</span>
</span></span><span class="line"><span class="cl"><span class="n">Number</span> <span class="n">of</span> <span class="n">sections</span><span class="err">:</span> <span class="mf">7</span>
</span></span><span class="line"><span class="cl"><span class="n">TimeDateStamp</span> <span class="err">:</span> <span class="mf">0</span>
</span></span><span class="line"><span class="cl"><span class="n">PointerToSymbolTable</span> <span class="err">:</span> <span class="n">0x2C2</span>
</span></span><span class="line"><span class="cl"><span class="n">NumberOfSymbols</span><span class="err">:</span> <span class="mf">21</span>
</span></span><span class="line"><span class="cl"><span class="n">OptionalHeaderSize</span><span class="err">:</span> <span class="mf">0</span>
</span></span><span class="line"><span class="cl"><span class="n">Characteristics</span><span class="err">:</span> <span class="mf">4</span>
</span></span><span class="line"><span class="cl"><span class="p">...</span>
</span></span><span class="line"><span class="cl"><span class="err">:</span> <span class="n">Section</span><span class="err">:</span> <span class="mf">0</span><span class="p">,</span> <span class="n">Value</span><span class="err">:</span> <span class="n">0x0</span>
</span></span><span class="line"><span class="cl">        <span class="err">:</span> <span class="n">Section</span><span class="err">:</span> <span class="mf">7</span><span class="p">,</span> <span class="n">Value</span><span class="err">:</span> <span class="n">0x0</span>
</span></span><span class="line"><span class="cl">        <span class="mf">8</span><span class="err">:</span> <span class="n">Section</span><span class="err">:</span> <span class="mf">0</span><span class="p">,</span> <span class="n">Value</span><span class="err">:</span> <span class="n">0x0</span>
</span></span><span class="line"><span class="cl">        <span class="err">:</span> <span class="n">Section</span><span class="err">:</span> <span class="mf">0</span><span class="p">,</span> <span class="n">Value</span><span class="err">:</span> <span class="n">0x0</span>
</span></span><span class="line"><span class="cl">        <span class="err">:</span> <span class="n">Section</span><span class="err">:</span> <span class="mf">0</span><span class="p">,</span> <span class="n">Value</span><span class="err">:</span> <span class="n">0x0</span>
</span></span><span class="line"><span class="cl">        <span class="err">:</span> <span class="n">Section</span><span class="err">:</span> <span class="mf">0</span><span class="p">,</span> <span class="n">Value</span><span class="err">:</span> <span class="n">0x0</span>
</span></span><span class="line"><span class="cl"><span class="n">Back</span>
</span></span><span class="line"><span class="cl"><span class="n">Returning</span>
</span></span><span class="line"><span class="cl"><span class="n">Ran</span><span class="p">/</span><span class="n">parsed</span> <span class="n">the</span> <span class="n">coff</span>
</span></span><span class="line"><span class="cl"><span class="n">Outdata</span> <span class="n">Below</span><span class="err">:</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">Current</span> <span class="k">process</span> <span class="n">id</span><span class="err">:</span> <span class="mf">9028</span>
</span></span><span class="line"><span class="cl"><span class="n">Username</span><span class="err">:</span> <span class="n">User</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nb">PS </span><span class="n">C:</span><span class="p">\</span><span class="n">Users</span><span class="p">\</span><span class="n">User</span><span class="p">\</span><span class="n">Documents</span><span class="p">\</span><span class="nb">writing-bofs</span><span class="n">-without-dfr-example</span><span class="p">&gt;</span>
</span></span></code></pre></div><p>That command line flag is the only thing needed to get this BOF working. The source can stay how it is without needing the DFR declarations.</p>
<p>Having to specify the import renaming on the command line every time can become difficult to manage as more imports are added. This can be simplified by storing the name mappings inside a dedicated file.</p>
<h3 id="adding-an-importstxt">Adding An Imports.txt</h3>
<p>Objcopy has a <code>--redefine-syms</code> flag which allows specifying a file with the list of symbol redefinitions instead of needing to pass them on the command line each time. The format for this file is: the current symbol name, a space, and the new name for the symbol. These redefinitions can be listed multiple times in the file on separate lines.</p>
<p>Here is how to create an imports.txt file for the example BOF above.</p>
<hr>
<p>Filename: <code>imports.txt</code></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-txt" data-lang="txt"><span class="line"><span class="cl">__imp_GetCurrentProcessId __imp_KERNEL32$GetCurrentProcessId
</span></span><span class="line"><span class="cl">__imp_GetUserNameA __imp_ADVAPI32$GetUserNameA
</span></span></code></pre></div><hr>
<p>Rerunning objcopy with the symbols specified in the <code>imports.txt</code> file should redefine all of the needed BOF imports.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">objcopy --redefine-syms<span class="o">=</span>imports.txt example.bof.o example-redefined.bof.o
</span></span></code></pre></div><p>Checking the symbol table with rabin2 confirms that the new symbol names were applied correctly.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">matt@laptop :: ~/Documents/dev/writing-bofs-without-dfr-example &gt;&gt; rabin2 -s example-redefined.bof.o
</span></span><span class="line"><span class="cl"><span class="o">[</span>Symbols<span class="o">]</span>
</span></span><span class="line"><span class="cl">nth paddr      vaddr      <span class="nb">bind</span>   <span class="nb">type</span> size lib name                                   demangled
</span></span><span class="line"><span class="cl">―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
</span></span><span class="line"><span class="cl"><span class="m">0</span>   0x00000000 0x00000000 LOCAL  FILE <span class="m">4</span>        .file
</span></span><span class="line"><span class="cl"><span class="m">0</span>   0x0000012c 0x00000000 GLOBAL FUNC <span class="m">4</span>        go
</span></span><span class="line"><span class="cl"><span class="m">0</span>   0x0000012c 0x00000000 LOCAL  SECT <span class="m">4</span>        .text
</span></span><span class="line"><span class="cl"><span class="m">0</span>   0x00000000 0x000000b0 LOCAL  SECT <span class="m">4</span>        .data
</span></span><span class="line"><span class="cl"><span class="m">0</span>   0x00000000 0x000000c0 LOCAL  SECT <span class="m">4</span>        .bss
</span></span><span class="line"><span class="cl"><span class="m">0</span>   0x000001dc 0x000000d0 LOCAL  SECT <span class="m">4</span>        .rdata
</span></span><span class="line"><span class="cl"><span class="m">0</span>   0x0000020c 0x00000100 LOCAL  SECT <span class="m">4</span>        .xdata
</span></span><span class="line"><span class="cl"><span class="m">0</span>   0x0000021c 0x00000110 LOCAL  SECT <span class="m">4</span>        .pdata
</span></span><span class="line"><span class="cl"><span class="m">0</span>   0x00000228 0x00000120 LOCAL  UNK  <span class="m">4</span>        .rdata<span class="nv">$zzz</span>
</span></span><span class="line"><span class="cl"><span class="m">0</span>   ---------- ---------- NONE   UNK  <span class="m">4</span>        imp.__imp_KERNEL32<span class="nv">$GetCurrentProcessId</span>
</span></span><span class="line"><span class="cl"><span class="m">0</span>   ---------- ---------- NONE   UNK  <span class="m">4</span>        imp.__imp_BeaconPrintf
</span></span><span class="line"><span class="cl"><span class="m">0</span>   ---------- ---------- NONE   UNK  <span class="m">4</span>        imp.__imp_ADVAPI32<span class="nv">$GetUserNameA</span>
</span></span></code></pre></div><p>This provides a way of specifying the BOF imports in a separate file outside of the source code itself. The BOF can be written like any other normal C program without needing to make special BOF-specific adjustments for managing imports.</p>
<h2 id="so-how-does-this-work">So How Does This Work?</h2>
<p>This will do a deep dive into what <em>exactly</em> objcopy is doing under the hood to make this work. Objcopy is from the <strong>GNU</strong> Binutils, so that means it may not work well on non-free platforms *cough cough Windows*. LLVM has their own version of objcopy (<a href="https://llvm.org/docs/CommandGuide/llvm-objcopy.html" target="_blank" rel="noopener noreffer ">llvm-objcopy</a>) which does work on Windows; however, it may be nice to have a standalone tool dedicated to this. A custom tool can add a lot of flexibility or other features that cater more towards BOF development.</p>
<p>Before diving in, it is good to get familiar with the raw file structure of a COFF. Not just what each of the components (file header, section headers, relocations, etc.) are but also where they are located inside the raw file. Taking a hex dump of a COFF and labeling each component would look like this.</p>
<hr>
<p>Hexdump output for <code>examplebof.bof.o</code></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-txt" data-lang="txt"><span class="line"><span class="cl">───────────────────────────────────────────────────────────────────
</span></span><span class="line"><span class="cl">00000000: 6486 0700 0000 0000 c202 0000 1500 0000  d............... COFF File Header
</span></span><span class="line"><span class="cl">                   ┌───────────────────────────────────────────────
</span></span><span class="line"><span class="cl">00000010: 0000 0400│2e74 6578 7400 0000 0000 0000  .....text....... COFF Section
</span></span><span class="line"><span class="cl">───────────────────┘                                                Headers
</span></span><span class="line"><span class="cl">00000020: 0000 0000 b000 0000 2c01 0000 6802 0000  ........,...h...
</span></span><span class="line"><span class="cl">00000030: 0000 0000 0600 0000 2000 5060 2e64 6174  ........ .P`.dat
</span></span><span class="line"><span class="cl">00000040: 6100 0000 0000 0000 0000 0000 0000 0000  a...............
</span></span><span class="line"><span class="cl">00000050: 0000 0000 0000 0000 0000 0000 0000 0000  ................
</span></span><span class="line"><span class="cl">00000060: 4000 50c0 2e62 7373 0000 0000 0000 0000  @.P..bss........
</span></span><span class="line"><span class="cl">00000070: 0000 0000 0000 0000 0000 0000 0000 0000  ................
</span></span><span class="line"><span class="cl">00000080: 0000 0000 0000 0000 8000 50c0 2e72 6461  ..........P..rda
</span></span><span class="line"><span class="cl">00000090: 7461 0000 0000 0000 0000 0000 3000 0000  ta..........0...
</span></span><span class="line"><span class="cl">000000a0: dc01 0000 0000 0000 0000 0000 0000 0000  ................
</span></span><span class="line"><span class="cl">000000b0: 4000 5040 2e78 6461 7461 0000 0000 0000  @.P@.xdata......
</span></span><span class="line"><span class="cl">000000c0: 0000 0000 1000 0000 0c02 0000 0000 0000  ................
</span></span><span class="line"><span class="cl">000000d0: 0000 0000 0000 0000 4000 3040 2e70 6461  ........@.0@.pda
</span></span><span class="line"><span class="cl">000000e0: 7461 0000 0000 0000 0000 0000 0c00 0000  ta..............
</span></span><span class="line"><span class="cl">000000f0: 1c02 0000 a402 0000 0000 0000 0300 0000  ................
</span></span><span class="line"><span class="cl">00000100: 4000 3040 2f34 0000 0000 0000 0000 0000  @.0@/4..........
</span></span><span class="line"><span class="cl">00000110: 0000 0000 4000 0000 2802 0000 0000 0000  ....@...(.......
</span></span><span class="line"><span class="cl">                             ┌─────────────────────────────────────
</span></span><span class="line"><span class="cl">00000120: 0000 0000 0000 0000│4000 5040 5557 4881  ........@.P@UWH. Raw data for
</span></span><span class="line"><span class="cl">─────────────────────────────┘                                      each section
</span></span><span class="line"><span class="cl">00000130: ec48 0100 0048 8dac 2480 0000 0048 8b05  .H...H..$....H..
</span></span><span class="line"><span class="cl">00000140: 0000 0000 ffd0 8985 bc00 0000 8b85 bc00  ................
</span></span><span class="line"><span class="cl">00000150: 0000 4189 c048 8d05 0000 0000 4889 c2b9  ..A..H......H...
</span></span><span class="line"><span class="cl">00000160: 0000 0000 488b 0500 0000 00ff d048 8d55  ....H........H.U
</span></span><span class="line"><span class="cl">00000170: b0b8 0000 0000 b920 0000 0048 89d7 f348  ....... ...H...H
</span></span><span class="line"><span class="cl">00000180: ab48 89fa 8802 4883 c201 c745 ac01 0100  .H....H....E....
</span></span><span class="line"><span class="cl">00000190: 0048 8d55 ac48 8d45 b048 89c1 488b 0500  .H.U.H.E.H..H...
</span></span><span class="line"><span class="cl">000001a0: 0000 00ff d083 f801 751f 488d 45b0 4989  ........u.H.E.I.
</span></span><span class="line"><span class="cl">000001b0: c048 8d05 1800 0000 4889 c2b9 0000 0000  .H......H.......
</span></span><span class="line"><span class="cl">000001c0: 488b 0500 0000 00ff d090 4881 c448 0100  H.........H..H..
</span></span><span class="line"><span class="cl">000001d0: 005f 5dc3 9090 9090 9090 9090 4375 7272  ._].........Curr
</span></span><span class="line"><span class="cl">000001e0: 656e 7420 7072 6f63 6573 7320 6964 3a20  ent process id: 
</span></span><span class="line"><span class="cl">000001f0: 256c 7500 5573 6572 6e61 6d65 3a20 2573  %lu.Username: %s
</span></span><span class="line"><span class="cl">00000200: 0000 0000 0000 0000 0000 0000 0111 0585  ................
</span></span><span class="line"><span class="cl">00000210: 1103 0901 2900 0270 0150 0000 0000 0000  ....)..p.P......
</span></span><span class="line"><span class="cl">00000220: a800 0000 0000 0000 4743 433a 2028 474e  ........GCC: (GN
</span></span><span class="line"><span class="cl">00000230: 5529 2031 342e 312e 3120 3230 3234 3036  U) 14.1.1 202406
</span></span><span class="line"><span class="cl">00000240: 3037 2028 4665 646f 7261 204d 696e 4757  07 (Fedora MinGW
</span></span><span class="line"><span class="cl">00000250: 2031 342e 312e 312d 332e 6663 3430 2900   14.1.1-3.fc40).
</span></span><span class="line"><span class="cl">                             ┌─────────────────────────────────────
</span></span><span class="line"><span class="cl">00000260: 0000 0000 0000 0000│1400 0000 1200 0000  ................ Relocation data
</span></span><span class="line"><span class="cl">─────────────────────────────┘
</span></span><span class="line"><span class="cl">00000270: 0400 2c00 0000 0a00 0000 0400 3b00 0000  ..,.........;...
</span></span><span class="line"><span class="cl">00000280: 1300 0000 0400 7300 0000 1400 0000 0400  ......s.........
</span></span><span class="line"><span class="cl">00000290: 8800 0000 0a00 0000 0400 9700 0000 1300  ................
</span></span><span class="line"><span class="cl">000002a0: 0000 0400 0000 0000 0400 0000 0300 0400  ................
</span></span><span class="line"><span class="cl">000002b0: 0000 0400 0000 0300 0800 0000 0c00 0000  ................
</span></span><span class="line"><span class="cl">              ┌────────────────────────────────────────────────────
</span></span><span class="line"><span class="cl">000002c0: 0300│2e66 696c 6500 0000 0000 0000 feff  ...file......... Symbol Table
</span></span><span class="line"><span class="cl">──────────────┘
</span></span><span class="line"><span class="cl">000002d0: 0000 6701 6578 616d 706c 6562 6f66 2e63  ..g.examplebof.c
</span></span><span class="line"><span class="cl">000002e0: 0000 0000 0000 676f 0000 0000 0000 0000  ......go........
</span></span><span class="line"><span class="cl">000002f0: 0000 0100 2000 0201 0000 0000 0000 0000  .... ...........
</span></span><span class="line"><span class="cl">00000300: 0000 0000 0000 0000 0000 2e74 6578 7400  ...........text.
</span></span><span class="line"><span class="cl">00000310: 0000 0000 0000 0100 0000 0301 a800 0000  ................
</span></span><span class="line"><span class="cl">00000320: 0600 0000 0000 0000 0000 0000 0000 2e64  ...............d
</span></span><span class="line"><span class="cl">00000330: 6174 6100 0000 0000 0000 0200 0000 0301  ata.............
</span></span><span class="line"><span class="cl">00000340: 0000 0000 0000 0000 0000 0000 0000 0000  ................
</span></span><span class="line"><span class="cl">00000350: 0000 2e62 7373 0000 0000 0000 0000 0300  ...bss..........
</span></span><span class="line"><span class="cl">00000360: 0000 0301 0000 0000 0000 0000 0000 0000  ................
</span></span><span class="line"><span class="cl">00000370: 0000 0000 0000 2e72 6461 7461 0000 0000  .......rdata....
</span></span><span class="line"><span class="cl">00000380: 0000 0400 0000 0301 2500 0000 0000 0000  ........%.......
</span></span><span class="line"><span class="cl">00000390: 0000 0000 0000 0000 0000 2e78 6461 7461  ...........xdata
</span></span><span class="line"><span class="cl">000003a0: 0000 0000 0000 0500 0000 0301 1000 0000  ................
</span></span><span class="line"><span class="cl">000003b0: 0000 0000 0000 0000 0000 0000 0000 2e70  ...............p
</span></span><span class="line"><span class="cl">000003c0: 6461 7461 0000 0000 0000 0600 0000 0301  data............
</span></span><span class="line"><span class="cl">000003d0: 0c00 0000 0300 0000 0000 0000 0000 0000  ................
</span></span><span class="line"><span class="cl">000003e0: 0000 0000 0000 0f00 0000 0000 0000 0700  ................
</span></span><span class="line"><span class="cl">000003f0: 0000 0301 3800 0000 0000 0000 0000 0000  ....8...........
</span></span><span class="line"><span class="cl">00000400: 0000 0000 0000 0000 0000 1a00 0000 0000  ................
</span></span><span class="line"><span class="cl">00000410: 0000 0000 0000 0200 0000 0000 3400 0000  ............4...
</span></span><span class="line"><span class="cl">00000420: 0000 0000 0000 0000 0200 0000 0000 4700  ..............G.
</span></span><span class="line"><span class="cl">                                       ┌───────────────────────────
</span></span><span class="line"><span class="cl">00000430: 0000 0000 0000 0000 0000 0200│5a00 0000  ............Z... String Table
</span></span><span class="line"><span class="cl">───────────────────────────────────────┘
</span></span><span class="line"><span class="cl">00000440: 2e72 6461 7461 247a 7a7a 002e 7264 6174  .rdata$zzz..rdat
</span></span><span class="line"><span class="cl">00000450: 6124 7a7a 7a00 5f5f 696d 705f 4765 7443  a$zzz.__imp_GetC
</span></span><span class="line"><span class="cl">00000460: 7572 7265 6e74 5072 6f63 6573 7349 6400  urrentProcessId.
</span></span><span class="line"><span class="cl">00000470: 5f5f 696d 705f 4265 6163 6f6e 5072 696e  __imp_BeaconPrin
</span></span><span class="line"><span class="cl">00000480: 7466 005f 5f69 6d70 5f47 6574 5573 6572  tf.__imp_GetUser
</span></span><span class="line"><span class="cl">00000490: 4e61 6d65 4100                           NameA.
</span></span><span class="line"><span class="cl">───────────────────────────────────────────────────────────────────
</span></span></code></pre></div><hr>
<p>The important parts are the symbol table, section headers, and the string table. Conveniently, the string table is located at the end of the file.</p>
<p>How do these bits relate to each other? The symbol table and section headers contain string data which may reference the string table. Each structure will set aside 8 bytes in the name field for holding this string data.</p>
<p>The formats for the name fields are outlined in the <a href="https://learn.microsoft.com/en-us/windows/win32/debug/pe-format#section-table-section-headers" target="_blank" rel="noopener noreffer ">Section Table (Section Headers)</a> and the <a href="https://learn.microsoft.com/en-us/windows/win32/debug/pe-format#coff-symbol-table" target="_blank" rel="noopener noreffer ">COFF Symbol Table</a> PE format documentation.</p>
<p>This can be examined by looking at the entry for the <code>.text</code> section in the hex dump above.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-txt" data-lang="txt"><span class="line"><span class="cl">                                               Name (8 bytes)
</span></span><span class="line"><span class="cl">                                                 │
</span></span><span class="line"><span class="cl">                   ╭───────────────────┬─────────┴────┬─────╮
</span></span><span class="line"><span class="cl">00000010:          │2e74 6578 7400 0000│0000 0000     │.text│......
</span></span><span class="line"><span class="cl">                   ╰───────────────────╯              ╰─────╯
</span></span><span class="line"><span class="cl">00000020: 0000 0000 b000 0000 2c01 0000 6802 0000  ........,...h...
</span></span><span class="line"><span class="cl">00000030: 0000 0000 0600 0000 2000 5060            ........ .P`    
</span></span></code></pre></div><p>Since the name for this section can fit in the 8 bytes set aside for the name field, it is embedded inline with the section metadata.</p>
<p>What happens if the section name is longer than 8 bytes?</p>
<p>That is where the string table comes into play. Instead of the name field containing the name of the section, it will contain a forward slash (/) at the start and then an ASCII number with the index into the string table where the name of the section lies.</p>
<p>This occurs with the last section header in the above hex dump example.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-txt" data-lang="txt"><span class="line"><span class="cl">                The name field in this instance is &#34;/4&#34; meaning that the name
</span></span><span class="line"><span class="cl">                of the section is really in the string table starting at the
</span></span><span class="line"><span class="cl">                fourth index.
</span></span><span class="line"><span class="cl">                                               Name (8 bytes)
</span></span><span class="line"><span class="cl">                                                 │
</span></span><span class="line"><span class="cl">                   ╭───────────────────┬─────────┴────┬────────╮
</span></span><span class="line"><span class="cl">00000100:          │2f34 0000 0000 0000│0000 0000     │/4......│....
</span></span><span class="line"><span class="cl">                   ╰───────────────────╯              ╰────────╯
</span></span><span class="line"><span class="cl">00000110: 0000 0000 4000 0000 2802 0000 0000 0000  ....@...(.......
</span></span><span class="line"><span class="cl">00000120: 0000 0000 0000 0000                      ........
</span></span></code></pre></div><p>And the value in the string table at that index is &ldquo;.rdata$zzz&rdquo;.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-txt" data-lang="txt"><span class="line"><span class="cl">        Real name of the section
</span></span><span class="line"><span class="cl">                 │
</span></span><span class="line"><span class="cl">00000430:        │                      5a00 0000              Z...
</span></span><span class="line"><span class="cl">         ╭───────┴───────────────────┬─────────────┬──────────╮
</span></span><span class="line"><span class="cl">00000440:│2e72 6461 7461 247a 7a7a 00│2e 7264 6174 │.rdata$zzz│.rdat
</span></span><span class="line"><span class="cl">         ╰───────────────────────────╯             ╰──────────╯
</span></span><span class="line"><span class="cl">00000450: 6124 7a7a 7a00 5f5f 696d 705f 4765 7443  a$zzz.__imp_GetC
</span></span><span class="line"><span class="cl">00000460: 7572 7265 6e74 5072 6f63 6573 7349 6400  urrentProcessId.
</span></span><span class="line"><span class="cl">00000470: 5f5f 696d 705f 4265 6163 6f6e 5072 696e  __imp_BeaconPrin
</span></span><span class="line"><span class="cl">00000480: 7466 005f 5f69 6d70 5f47 6574 5573 6572  tf.__imp_GetUser
</span></span><span class="line"><span class="cl">00000490: 4e61 6d65 4100                           NameA.
</span></span></code></pre></div><p>One important thing to note is where this index is based from in the string table. The first four bytes of the string table (0x43c &ndash; 0x43f) is the size field. This is a little-endian integer (0x5a) that contains the size of the string table including the size field itself. The data for the string table starts at 0x440 with the size of that data being the value in the size field minus the size of that field (0x5a - 4 = 0x56).</p>
<p>The index defined in the section header is not based from the start of the string table data but rather the start of the string table including the size field.</p>
<p>Symbol names follow the same pattern but with one difference. The difference is outlined in the <a href="https://learn.microsoft.com/en-us/windows/win32/debug/pe-format#symbol-name-representation" target="_blank" rel="noopener noreffer ">Symbol Name Representation</a> PE format documentation.</p>
<p>Instead of the first byte of the name starting with a forward slash to signify that the name string is located in the string table, the first four bytes of the name field will be set to NULL and the next four bytes are the string table index. This index is a regular 4 byte, little-endian integer rather than an ASCII decimal number like in the section headers. The name index in the symbol table follows the same rule as the section header name where that index is based from the beginning of the string table starting at the size field instead of where the string data starts.</p>
<p>In the example hex dump, the last symbol in the symbol table contains a symbol name longer than 8 bytes.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-txt" data-lang="txt"><span class="line"><span class="cl">           First four bytes are all 0
</span></span><span class="line"><span class="cl">                                   │     The symbol name is in the string
</span></span><span class="line"><span class="cl">                                   │     table at index 0x47
</span></span><span class="line"><span class="cl">                                   │            │
</span></span><span class="line"><span class="cl">                                  ╭┴────────┬───┴╮
</span></span><span class="line"><span class="cl">00000420:                         │0000 0000│4700│           ....G.
</span></span><span class="line"><span class="cl">                                  ╰─────────┤    │
</span></span><span class="line"><span class="cl">         ╭──────────────────────────────────╯    │
</span></span><span class="line"><span class="cl">         │    ╭──────────────────────────────────╯
</span></span><span class="line"><span class="cl">00000430:│0000│0000 0000 0000 0000 0200            ............
</span></span><span class="line"><span class="cl">         ╰────╯
</span></span></code></pre></div><p>The string table</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-txt" data-lang="txt"><span class="line"><span class="cl">00000430:                               5a00 0000               Z...
</span></span><span class="line"><span class="cl">00000440: 2e72 6461 7461 247a 7a7a 002e 7264 6174   .rdata$zzz..rdat
</span></span><span class="line"><span class="cl">00000450: 6124 7a7a 7a00 5f5f 696d 705f 4765 7443   a$zzz.__imp_GetC
</span></span><span class="line"><span class="cl">00000460: 7572 7265 6e74 5072 6f63 6573 7349 6400   urrentProcessId.
</span></span><span class="line"><span class="cl">00000470: 5f5f 696d 705f 4265 6163 6f6e 5072 696e   __imp_BeaconPrin
</span></span><span class="line"><span class="cl">                 ╭────────────────────────────────╮   ┌─────────────╮
</span></span><span class="line"><span class="cl">00000480: 7466 00│5f 5f69 6d70 5f47 6574 5573 6572│ tf│__imp_GetUser│
</span></span><span class="line"><span class="cl">         ╭───────┘      ╭─────────┬───────────────┴┬──┘  ┌──────────┘
</span></span><span class="line"><span class="cl">00000490:│4e61 6d65 4100│         │                │NameA│
</span></span><span class="line"><span class="cl">         └──────────────┘         │                └─────┘
</span></span><span class="line"><span class="cl">                                  │
</span></span><span class="line"><span class="cl">               The name of this symbol is &#34;__imp_GetUserNameA&#34;
</span></span></code></pre></div><p>This shows how the string table is connected to the section headers and the symbol table. Now, on to how the symbol renaming works.</p>
<h3 id="diy-symbol-renaming">DIY Symbol Renaming</h3>
<p>Due to the nature of how the section headers and symbol table interact with the string table, the action of renaming a symbol is pretty straightforward.</p>
<p>The first thing to do is to find the symbol table entry of the symbol which needs to be renamed. The name field will either hold the symbol name as a byte string or an index into the string table depending on if the name is longer than 8 bytes. If the current symbol name and new name it needs to be renamed to are both 8 bytes in length or less, the new name can be inserted directly into the name field replacing the old value. Nothing else in the COFF needs to be modified.</p>
<p>It is a lot more common for symbol names to be longer than 8 bytes which requires a little bit more work. There are a few ways that a symbol can be renamed but this will go over the &ldquo;naive&rdquo; way and another way by directly replacing the old string with the new one in the string table.</p>
<h4 id="the-naive-way">The Naive Way</h4>
<p>Remember earlier in this blog post during the section explaining the COFF file layout it was mentioned that the string table is &ldquo;conveniently&rdquo; located at the end of the file? The reason this is convenient is because arbitrary strings can be appended to it without needing to update other parts of the COFF!</p>
<p>COFF metadata will occasionally contain references to other parts of the file. Inserting or removing any data in the middle of the file will cause various components to shift around. This requires going back through the COFF to make sure any old file references are updated to account for this shift. Appending data does not cause this shift so the file references will stay valid.</p>
<p>To rename a symbol the naive way, the new symbol name can simply be appended to the end of the string table while updating the string table size field to account for the added string. All that is left to do is change the name field in the COFF symbol table entry to reference the newly added string. The rest of the COFF can stay as is since this method does not cause any other parts of the file to shift around. The old name string can be left where it is and it will simply exist as a couple extra bytes of unused data.</p>
<p>This approach may not be the most ideal when a lot of symbols need to be renamed since the old symbol names will take up space.</p>
<h4 id="replacing-the-current-string-table-entry-with-the-new-one">Replacing the Current String Table Entry with the New One</h4>
<p>Another option for renaming a symbol is by replacing the current symbol name in the string table with the new name. The only difference here is that the other string table references in the section headers and symbol table will need to be adjusted to account for any shifts. If a symbol needs to be renamed with a new name 9 bytes longer than the original one, any section headers or symbol table entries that reference strings past this string will need their indexes increased by 9 due to the size change.</p>
<h2 id="wrapping-up">Wrapping Up</h2>
<p>The purpose of this blog post is to showcase a lesser known tool from the GNU Binutils that people may not be too familiar with. Its ability to redefine symbols inside an object file is something that can be utilized in Beacon Object File development. BOFs do not need their imports to be manually declared in DFR format inside the source code. They can be managed separately while the code focuses more on what the BOF is being developed to do. Keeping the source code more inline with how traditional C code is written allows it to better integrate with existing development tools.</p>
<p>Another takeaway is the concept of &ldquo;decoupling&rdquo; the constraints of software designed to run in atypical environments from the software itself. Keeping the software more generic makes it easier to work with when needing to test or debug it. Finding alternative ways of dealing with these constraints outside of the code, either through libraries or other tooling, means that the code can focus only on what it is being designed to do while the various environmental factors are handled elsewhere.</p>
<p>Using a dedicated tool for managing imported functions in Beacon Object Files is one example of how this decoupling concept can be applied.</p>
]]></description></item><item><title>Thanatos: Installation and Usage</title><link>https://blog.cybershenanigans.space/posts/thanatos-agent-usage/</link><pubDate>Thu, 24 Mar 2022 13:00:01 -0500</pubDate><author>Matt Ehrnschwender</author><guid>https://blog.cybershenanigans.space/posts/thanatos-agent-usage/</guid><description><![CDATA[<p>This is part two of a series of blog posts on Thanatos, a Mythic C2 agent written in
Rust. This post will go over setting up Mythic and Thanatos in an Ubuntu VM and the agent&rsquo;s
usage.</p>
<p><a href="/posts/thanatos-agent" rel="">Part one</a> of the series discusses how this project came about and the development of it.</p>
<p>Project repository:
<a href="https://github.com/MythicAgents/thanatos" target="_blank" rel="noopener noreffer ">https://github.com/MythicAgents/thanatos</a></p>
<h1 id="overview">Overview</h1>
<ul>
<li><a href="#thanatos-features-and-functionality" rel="">Thanatos Features and Functionality</a>
<ul>
<li><a href="#installing-mythic-with-thanatos" rel="">Installing Mythic with Thanatos</a>: Setting up Mythic and Thanatos on an Ubuntu VM</li>
<li><a href="#building-the-agent" rel="">Building the Agent</a>: How to build the payload</li>
<li><a href="#using-the-agent" rel="">Using the Agent</a>: Basic functionality</li>
<li><a href="#unique-capabilities" rel="">Unique Capabilities</a>: Features which standout compared to other C2 agents</li>
</ul>
</li>
<li><a href="#future-improvements" rel="">Future Improvements</a></li>
</ul>
<h1 id="thanatos-features-and-functionality">Thanatos Features and Functionality</h1>
<p>If you&rsquo;re new to Mythic, I highly recommend checking out the <a href="https://docs.mythic-c2.net/" target="_blank" rel="noopener noreffer ">Mythic Documentation</a>.
Mythic is very unique compared to other C2 frameworks due to its modular design. Other
frameworks such as Cobalt Strike or Empire include a full suite of modules including: C2
profiles/transports, stagers, payloads a UI, etc. Mythic decides to take these common
features of a C2 framework and split them up into three distinct server, C2 profiles and
payload types modules. Due to this design, payloads can vary from compiled .NET Windows
executables to chrome web browser extensions. C2 profiles give the operator and developers flexibility on how
their payloads communicate with Mythic. This allows a very high level of flexibility to
tune the operation based on what the target is. The currently public C2 profiles are HTTP,
DNS and websocket but profiles can be developed which utilize AWS S3 buckets, Microsoft Teams,
Dropbox or various other mediums for communication.</p>
<p>It&rsquo;s important to note this modular aspect when using Mythic since it provides a somewhat unique
experience when performing red team operations.</p>
<h3 id="installing-mythic-with-thanatos">Installing Mythic with Thanatos</h3>
<p>Setting up a machine with Mythic and installing Thanatos is very straight forward thanks to
Mythic&rsquo;s use of Docker containers. Along the that, there is a convenient <code>mythic-cli</code> program which
can be used instead of manually setting up and running all of the images.</p>
<p>The first thing to do is setup Linux machine and install docker. For this example I will be
using Ubuntu 20.04 in a virtual machine.</p>
<p>Be sure you allocate enough resources to your machine. I will be using a virtual machine with 20GB
of hard drive space, 8GB of ram and 2 vCPUs.</p>
<p>After Linux is setup, <code>docker</code> and <code>docker-compose</code> need to be installed.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo apt update
</span></span><span class="line"><span class="cl">sudo apt install docker.io docker-compose
</span></span></code></pre></div><p>Ensure the docker daemon has been started and set to start on boot</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo systemctl <span class="nb">enable</span> --now docker
</span></span></code></pre></div><p>Next, clone the Mythic repository from Github. This can be cloned to anywhere on the
machine.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">git clone https://github.com/its-a-feature/Mythic.git --depth <span class="m">1</span>
</span></span></code></pre></div><p>The <code>--depth 1</code> is optional but it makes the download significantly faster.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">ubuntu@mythic-server:~$ git clone https://github.com/its-a-feature/Mythic.git --depth <span class="m">1</span>
</span></span><span class="line"><span class="cl">Cloning into <span class="s1">&#39;Mythic&#39;</span>...
</span></span><span class="line"><span class="cl">remote: Enumerating objects: 2245, <span class="k">done</span>.
</span></span><span class="line"><span class="cl">remote: Counting objects: 100% <span class="o">(</span>2245/2245<span class="o">)</span>, <span class="k">done</span>.
</span></span><span class="line"><span class="cl">remote: Compressing objects: 100% <span class="o">(</span>1983/1983<span class="o">)</span>, <span class="k">done</span>.
</span></span><span class="line"><span class="cl">remote: Total <span class="m">2245</span> <span class="o">(</span>delta 276<span class="o">)</span>, reused <span class="m">2112</span> <span class="o">(</span>delta 231<span class="o">)</span>, pack-reused <span class="m">0</span>
</span></span><span class="line"><span class="cl">Receiving objects: 100% <span class="o">(</span>2245/2245<span class="o">)</span>, 24.81 MiB <span class="p">|</span> 17.27 MiB/s, <span class="k">done</span>.
</span></span><span class="line"><span class="cl">Resolving deltas: 100% <span class="o">(</span>276/276<span class="o">)</span>, <span class="k">done</span>.
</span></span><span class="line"><span class="cl">ubuntu@mythic-server:~$ <span class="nb">cd</span> Mythic/
</span></span><span class="line"><span class="cl">ubuntu@mythic-server:~/Mythic$ ls
</span></span><span class="line"><span class="cl">C2_Profiles           Example_Payload_Type      install_docker_kali.sh    mythic-docker        postgres-docker  SECURITY.md
</span></span><span class="line"><span class="cl">docker-compose.yml    Example_Translator        install_docker_ubuntu.sh  mythic-react-docker  rabbitmq-docker  VERSION
</span></span><span class="line"><span class="cl">documentation-docker  hasura-docker             LICENSE                   nginx-docker         README.md
</span></span><span class="line"><span class="cl">Example_C2_Profile    install_docker_debian.sh  mythic-cli                Payload_Types        redis-docker
</span></span><span class="line"><span class="cl">ubuntu@mythic-server:~/Mythic$
</span></span></code></pre></div><p>The newly cloned Mythic repo contains a <code>mythic-cli</code> program. This program is used for
managing the framework.</p>
<p>Configuring the server is done through a <code>.env</code> file located in the Mythic directory. To
generate this configuration file run <code>./mythic-cli config</code></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">ubuntu@mythic-server:~/Mythic$ ./mythic-cli config
</span></span><span class="line"><span class="cl"><span class="nv">ALLOWED_IP_BLOCKS</span> <span class="o">=</span> 0.0.0.0/0
</span></span><span class="line"><span class="cl"><span class="nv">COMPOSE_PROJECT_NAME</span> <span class="o">=</span> mythic
</span></span><span class="line"><span class="cl"><span class="nv">DEFAULT_OPERATION_NAME</span> <span class="o">=</span> Operation Chimera
</span></span><span class="line"><span class="cl"><span class="nv">DOCUMENTATION_BIND_LOCALHOST_ONLY</span> <span class="o">=</span> <span class="nb">true</span>
</span></span><span class="line"><span class="cl"><span class="nv">DOCUMENTATION_HOST</span> <span class="o">=</span> mythic_documentation
</span></span><span class="line"><span class="cl"><span class="nv">DOCUMENTATION_PORT</span> <span class="o">=</span> <span class="m">8090</span>
</span></span><span class="line"><span class="cl"><span class="nv">EXCLUDED_C2_PROFILES</span> <span class="o">=</span>
</span></span><span class="line"><span class="cl"><span class="nv">EXCLUDED_PAYLOAD_TYPES</span> <span class="o">=</span>
</span></span><span class="line"><span class="cl"><span class="nv">HASURA_BIND_LOCALHOST_ONLY</span> <span class="o">=</span> <span class="nb">true</span>
</span></span><span class="line"><span class="cl"><span class="nv">HASURA_HOST</span> <span class="o">=</span> mythic_graphql
</span></span><span class="line"><span class="cl"><span class="nv">HASURA_PORT</span> <span class="o">=</span> <span class="m">8080</span>
</span></span><span class="line"><span class="cl"><span class="nv">HASURA_SECRET</span> <span class="o">=</span> bWeMjZIlXjbl54NWlW0GoHv2FJOnhH
</span></span><span class="line"><span class="cl"><span class="nv">JWT_SECRET</span> <span class="o">=</span> ZxkLIpPB5HbH8LNU3kvTpkxS6epnPU
</span></span><span class="line"><span class="cl"><span class="nv">MYTHIC_ADMIN_PASSWORD</span> <span class="o">=</span> 2Kszg9c5fRUDapU1TF9UxNzpfn16HA
</span></span><span class="line"><span class="cl"><span class="nv">MYTHIC_ADMIN_USER</span> <span class="o">=</span> mythic_admin
</span></span><span class="line"><span class="cl"><span class="nv">MYTHIC_DEBUG</span> <span class="o">=</span> <span class="nb">false</span>
</span></span><span class="line"><span class="cl"><span class="nv">MYTHIC_ENVIRONMENT</span> <span class="o">=</span> production
</span></span><span class="line"><span class="cl"><span class="nv">MYTHIC_REACT_BIND_LOCALHOST_ONLY</span> <span class="o">=</span> <span class="nb">true</span>
</span></span><span class="line"><span class="cl"><span class="nv">MYTHIC_REACT_HOST</span> <span class="o">=</span> mythic_react
</span></span><span class="line"><span class="cl"><span class="nv">MYTHIC_REACT_PORT</span> <span class="o">=</span> <span class="m">3000</span>
</span></span><span class="line"><span class="cl"><span class="nv">MYTHIC_SERVER_BIND_LOCALHOST_ONLY</span> <span class="o">=</span> <span class="nb">true</span>
</span></span><span class="line"><span class="cl"><span class="nv">MYTHIC_SERVER_DYNAMIC_PORTS</span> <span class="o">=</span> 7000-7010
</span></span><span class="line"><span class="cl"><span class="nv">MYTHIC_SERVER_HOST</span> <span class="o">=</span> mythic_server
</span></span><span class="line"><span class="cl"><span class="nv">MYTHIC_SERVER_PORT</span> <span class="o">=</span> <span class="m">17443</span>
</span></span><span class="line"><span class="cl"><span class="nv">NGINX_BIND_LOCALHOST_ONLY</span> <span class="o">=</span> <span class="nb">false</span>
</span></span><span class="line"><span class="cl"><span class="nv">NGINX_HOST</span> <span class="o">=</span> mythic_nginx
</span></span><span class="line"><span class="cl"><span class="nv">NGINX_PORT</span> <span class="o">=</span> <span class="m">7443</span>
</span></span><span class="line"><span class="cl"><span class="nv">NGINX_USE_SSL</span> <span class="o">=</span> <span class="nb">true</span>
</span></span><span class="line"><span class="cl"><span class="nv">POSTGRES_BIND_LOCALHOST_ONLY</span> <span class="o">=</span> <span class="nb">true</span>
</span></span><span class="line"><span class="cl"><span class="nv">POSTGRES_DB</span> <span class="o">=</span> mythic_db
</span></span><span class="line"><span class="cl"><span class="nv">POSTGRES_HOST</span> <span class="o">=</span> mythic_postgres
</span></span><span class="line"><span class="cl"><span class="nv">POSTGRES_PASSWORD</span> <span class="o">=</span> zhqoomxZd3BsI1x5tcAnLTosiJjBRG
</span></span><span class="line"><span class="cl"><span class="nv">POSTGRES_PORT</span> <span class="o">=</span> <span class="m">5432</span>
</span></span><span class="line"><span class="cl"><span class="nv">POSTGRES_USER</span> <span class="o">=</span> mythic_user
</span></span><span class="line"><span class="cl"><span class="nv">RABBITMQ_BIND_LOCALHOST_ONLY</span> <span class="o">=</span> <span class="nb">true</span>
</span></span><span class="line"><span class="cl"><span class="nv">RABBITMQ_HOST</span> <span class="o">=</span> mythic_rabbitmq
</span></span><span class="line"><span class="cl"><span class="nv">RABBITMQ_PASSWORD</span> <span class="o">=</span> bIoU2A9M5vZTZ8LopdYpik2pktMDiJ
</span></span><span class="line"><span class="cl"><span class="nv">RABBITMQ_PORT</span> <span class="o">=</span> <span class="m">5672</span>
</span></span><span class="line"><span class="cl"><span class="nv">RABBITMQ_USER</span> <span class="o">=</span> mythic_user
</span></span><span class="line"><span class="cl"><span class="nv">RABBITMQ_VHOST</span> <span class="o">=</span> mythic_vhost
</span></span><span class="line"><span class="cl"><span class="nv">REBUILD_ON_START</span> <span class="o">=</span> <span class="nb">true</span>
</span></span><span class="line"><span class="cl"><span class="nv">REDIS_BIND_LOCALHOST_ONLY</span> <span class="o">=</span> <span class="nb">true</span>
</span></span><span class="line"><span class="cl"><span class="nv">REDIS_HOST</span> <span class="o">=</span> mythic_redis
</span></span><span class="line"><span class="cl"><span class="nv">REDIS_PORT</span> <span class="o">=</span> <span class="m">6379</span>
</span></span><span class="line"><span class="cl"><span class="nv">SERVER_HEADER</span> <span class="o">=</span> nginx 1.2
</span></span><span class="line"><span class="cl"><span class="nv">SIEM_LOG_NAME</span> <span class="o">=</span>
</span></span><span class="line"><span class="cl"><span class="nv">WEB_KEEP_LOGS</span> <span class="o">=</span> <span class="nb">false</span>
</span></span><span class="line"><span class="cl"><span class="nv">WEB_LOG_SIZE</span> <span class="o">=</span> <span class="m">1024000</span>
</span></span><span class="line"><span class="cl">ubuntu@mythic-server:~/Mythic$
</span></span></code></pre></div><p>The defaults can be kept the same; however, I am going to set a different admin password.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nv">MYTHIC_ADMIN_PASSWORD</span><span class="o">=</span><span class="s2">&#34;TestingPassword123!@#&#34;</span>
</span></span></code></pre></div><p>Since this is a test VM for a demo only reachable from my host machine, I am okay with using the
default Mythic admin user and an insecure password.</p>
<p>After that&rsquo;s done, it&rsquo;s time to install the Thanatos payload and HTTP C2 profile.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo ./mythic-cli install github https://github.com/MythicAgents/thanatos
</span></span><span class="line"><span class="cl">sudo ./mythic-cli install github https://github.com/MythicC2Profiles/http
</span></span></code></pre></div><p>Mythic can now be started</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo ./mythic-cli mythic start
</span></span></code></pre></div><p>This can take a fair bit of time depending on your network connection. Mythic has to
download all of the docker images for the server along with the docker images for the HTTP profile and Thanatos.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">real    3m4.578s
</span></span><span class="line"><span class="cl">user    0m2.149s
</span></span><span class="line"><span class="cl">sys     0m0.422s
</span></span></code></pre></div><p>If everything went well, Mythic should be reachable at <code>https://&lt;IP address&gt;:7443/</code> using
a web browser.</p>
<p>To make sure everything was set up correctly, log in using the password you set. The
username is <code>mythic_admin</code> unless you changed it during the configuration. Navigate to the
<code>C2 Profiles and Paylod Types</code> page by clicking on the headphones icon in the top left
corner.</p>
<p>Thanatos should be listed under the Payload Types and http under the C2 Profiles with a
green status icon.</p>
<p></p>
<blockquote>
<p>Note: &ldquo;tetanus&rdquo; was the old name for the Mythic agent. This is why the payload types entry has an agent named tetanus instead of thanatos.</p>
</blockquote>
<h3 id="building-the-agent">Building the Agent</h3>
<p>The build page can be reached by clicking on the <code>Payloads</code> icon on the top left of the
web page next to the <code>C2 Profiles and Payload Types</code> icon. In the drop down <code>Actions</code>
menu in the top left, click the <code>Generate New Payload</code> button.</p>
<p>This menu will prompt you to select the target OS. Thanatos only supports targeting Windows or Linux.
After the target OS is selected, the build parameters configuration will be available.</p>
<p></p>
<ol>
<li>
<p>The first build parameter is an option to configure how the agent should run. If this
options is set and the payload is built for Windows, the agent will hide the console window
when it is executed. For Linux, this option controls whether the agent should run in the
foreground or fork and run in the background.</p>
</li>
<li>
<p>The second build parameter controls how many attempts the agent should make for the
initial check in. If the agent fails to establish a connection when it is executed, it
will sleep for the configured interval and try to establish another connection. The
retries determine how many attempts the agent should make before it will stop. More
information about it can be found in the Mythic documentation.</p>
</li>
<li>
<p>The third parameter configures the output format for the payload file. Thanatos can be
built as a standalone executable, a shared library, or raw shellcode for Windows. The
shared library option will build a Windows DLL when targeting Windows and an
ELF shared object when targeting Linux. The raw shellcode for Windows can be used for
injecting the payload through various injection techniques or for developing obfuscation
wrappers. Picking the shellcode option when targeting Linux will result in the build
failing!</p>
</li>
<li>
<p>The fourth parameter controls static linking for Linux payloads. Statically linking the
payload will make the executable size larger; however, it will help ensure it can run on
all Linux platforms. This is recommended if trying to spawn the agent on a host using a
non glibc libc or on older Linux systems. This option has no effect when building payloads
for Windows.</p>
</li>
<li>
<p>The fifth parameter is the payload architecture. The payload can be built to target both 32 and 64
bit x86 systems.</p>
</li>
<li>
<p>The sixth parameter is the working hours. The working hours mean that the agent will only
make connections to Mythic during the configured time frame. This also includes the
initial check in. If the agent was executed when not in the configured working hours
period, it will not check in until the start of the working hours the next day. This
option can be changed during operation of the agent using the <code>workinghours</code> command. The
format for the working hours is <code>HH:MM-HH:MM</code> using 24 hour format. When operating, the
agent will use the targeted system&rsquo;s locally set time zone. Time zone calculations may be
needed in order to compensate for time differences.</p>
</li>
</ol>
<p>After the build parameters are set, the next menu will allow you to configure what
commands to build into the agent. The agent does not support dynamic compilation of
features so all commands are included.</p>
<p>The C2 profiles page only gives an option for HTTP. There are plans to include different
C2 profiles in the future.</p>
<p></p>
<p></p>
<ul>
<li>
<p>Callback Host</p>
<ul>
<li>Hostname or IP to connect to when beaconing back to Mythic.</li>
</ul>
</li>
<li>
<p>Callback Interval in seconds</p>
<ul>
<li>Sleep interval for the agent in seconds. This can be changed while interacting with
the agent using the <code>sleep</code> command.</li>
</ul>
</li>
<li>
<p>Callback Jitter in percent</p>
<ul>
<li>Jitter to apply for the agent&rsquo;s sleep interval. The agent will pick a random
percentage value between 0 and the configured jitter during each sleep time. The
jitter is randomly added or subtracted from the configured sleep interval during the
sleep time. If the sleep interval is set for 30 seconds and the jitter value is 50%,
the agent will choose a random sleep time between 15 to 45 seconds. This value can be
changed during operation using the <code>sleep</code> command.</li>
</ul>
</li>
<li>
<p>Callback Port</p>
<ul>
<li>Listening port of the server for http requests.</li>
</ul>
</li>
<li>
<p>Crypto type</p>
<ul>
<li>Choose whether the C2 traffic should be AES256 encrypted or if there should be no
encryption.</li>
</ul>
</li>
<li>
<p>GET request URI</p>
<ul>
<li>The URI for performing GET requests.</li>
</ul>
</li>
<li>
<p>HTTP Headers</p>
<ul>
<li>Addition HTTP headers for the agent.</li>
</ul>
</li>
<li>
<p>Kill Date</p>
<ul>
<li>Kill date of the agent</li>
</ul>
</li>
<li>
<p>Query Path Name</p>
<ul>
<li>Name of the query parameter for GET requests</li>
</ul>
</li>
<li>
<p>Perform Key Exchange</p>
<ul>
<li>Configure whether or not the agent should perform a key exchange during the initial
check in.</li>
</ul>
</li>
<li>
<p>Proxy Information</p>
<ul>
<li>Connecting to socks proxies from the agent to Mythic is currently unimplemented so
these proxy parameters can be left blank</li>
</ul>
</li>
</ul>
<p>Once the C2 profile information is set, the next page will allow you to name the payload
along with setting a description for it. The description for the payload will be the
initial description in the C2 callbacks page.</p>
<p>Once the payload creation has kicked off, it can take around 15 seconds to a few minutes for the agent to
build depending on VM resources. Thanatos will do dependency caching after the initial build
depending on target OS, architecture and static linking. For example, an initial x64
Windows agent build will take the pre-built dependencies and cache them. Future builds
targeting Windows x64 will take significantly less time as compared to the initial
build because the dependencies from the initial build are used.</p>
<p>The payload builder works this way to keep the initial size of the docker image smaller
while also shortening consecutive build times.
Not every operation is going to need the pre-build dependencies targeting 32 bit Linux;
therefore, those pre-built dependencies are not going to take up unnecessary disk space.</p>
<h3 id="using-the-agent">Using the Agent</h3>
<p>The basic agent operations are very similar to any other Mythic payload. Thanatos has a few
features which are slightly different than other Mythic payloads.</p>
<p>During initial check in for Linux hosts, Thanatos will query information about the Linux
kernel version and whether or not the agent is on an SELinux system. That information can
be found by clicking on the Linux icon under the OS section in the callback page.</p>
<p>
</p>
<p>Here is an example of what it will show. The kernel version of the system this payload is
running on is <code>5.16.12-200.fc35.x86_64</code> and it does have SELinux capabilities.</p>
<p>The interact row can be used to interact with the agent. The dropdown menu provides
various quick interactions. Clicking on the keyboard icon will pull up the command window
at the bottom of the screen.</p>
<p></p>
<p></p>
<p>Issuing <code>help</code> in the command window will show a list of all the available commands and a
brief description about them. More information about the available commands can be found
in the Mythic documentation.</p>
<p>The Mythic documentation can be reached by clicking on the question mark in the top right
corner and clicking on <code>Agent Documentation</code>. This page is where Mythic will store the
documentation about payload types and C2 profiles. The left side of the web page will have
a list of all the installed agents. Clicking on Thanatos will pull up the documentation for
the Thanatos payload. Clicking on the <code>Commands</code> menu on the left side of the web page will
bring up a list of all the commands Thanatos supports. Clicking on the command will take
you to that command&rsquo;s documentation.</p>
<p>Issuing tasking can be done using the Mythic popup UI or through named parameter flags.
The Mythic popup UI can be displayed by typing the command in the task Window and pressing
<code>Shift + Enter</code>. Commands and their parameters can also be issued directly through the
tasking prompt using named parameters or inline with the command.</p>
<p></p>
<p></p>
<p>Not every command supports entering arguments directly in the task prompt. Every command
does support the Mythic UI popup by pressing <code>Shift + Enter</code> after typing the command in
the tasking prompt. For more information about command parameter formats, refer to the documentation for the
command in the Mythic documentation.</p>
<p>Some commands support browser scripts. Browser scripts in Mythic allow more refined ways
of formatting the task output along with potentially issuing other tasking through the browser script.</p>
<p></p>
<p>In the <code>ls</code> example, the browser script allows for new tasking to be issued by clicking on
any of the tasking buttons. More browser script support is planned for the future since it
makes issuing more tasks very convenient.</p>
<h3 id="unique-capabilities">Unique Capabilities</h3>
<p>Thanatos features a few capabilities which other agents do not have. Starting with building
the agent, Thanatos allows the operator a lot of flexibility on choosing how to build the
agent. This flexibility includes controlling the output format, target architecture,
static linking and even whether or not the agent should daemonize. The operator can also
choose configuration for the C2 communications such as how many times the agent should
attempt to check in if the initial check in fails and what time throughout the day the
agent should make check ins to the C2.</p>
<p>Going into the operation of the agent, Thanatos currently has two distinct features that
are somewhat unique. The first being its SSH capabilities. The agent uses the
<a href="https://docs.rs/ssh2/latest/ssh2/" target="_blank" rel="noopener noreffer ">ssh2</a> library in order to make SSH connections. The
agent features a whole suite of commands which can all be executed over SSH. These include
executing shell commands, downloading and uploading files between the SSH connected
machine and Mythic, displaying the contents of files, grabbing directory listings and
removing files. Typing <code>ssh</code> into the tasking prompt for a callback and pressing <code>Shift + Enter</code> will display the capabilities and parameters.</p>
<p></p>
<p>The dropdown menu for the parameter group can be selected to choose what action you would like to perform over ssh.</p>
<p></p>
<p>All of the actions are documented in the Mythic documentation but I would like to
highlight the <code>List</code> action.</p>
<p>The first parameter for each ssh function is to select what credentials to use. The agent
will pull these credentials from the Mythic credential database. When creating a new
credential for ssh, the <code>plaintext</code> credential type means that the supplied credential is
a plain text username and password combination. A credential type of <code>key</code> signifies that
the supplied credential is an SSH private key. The only options in the Mythic credential
which need to be populated are the Account Name for the username of the account to log in
as for SSH and the Credential which is either the plain text password for the user or an
SSH private key.</p>
<p>Once the credential is selected, the use ssh agent option can be set to false. This tells
Thanatos whether it should use running ssh agents on the system for authentication instead
of through the Mythic credential. More information about that can be found in the
documentation for the <code>ssh-agent</code> command.</p>
<p>I have another Linux machine located at <code>192.168.122.56</code> where I know the username and
password for a user on that machine.</p>
<p></p>
<p>Once I submit the task, the agent will attempt to connect to that machine through SSH with
the ubuntu user and grab a directory listing of the root directory.</p>
<p></p>
<p>The SSH command features a browser script which will pull the time metadata and permissions
for each entry similar to the regular <code>ls</code> browser script. Along with that, the browser
script features the same context menus as the normal <code>ls</code> command. Through the browser
script, the operator can issue new SSH tasking to list different subdirectories or perform
other actions.</p>
<p></p>
<p>Tasking issued through the browser script will use the same credentials and host
information for the new task so the new task will be queued automatically without having
to manually fill out the task parameters.</p>
<p>This provides a very convenient way to interact with other machines through SSH without
having to spawn a payload on the machine.</p>
<hr>
<p>The second notable feature is the ability to stand up TCP redirectors through the <code>redirect</code> command.
The agent will listen for connections on a machine and relay them to another machine. This
is very useful when dealing with machines that do not have direct Internet access. A
redirector can be created which will redirect traffic from the machine to a server on the
Internet.</p>
<p>The redirect capability can also bring p2p-like functionality to other agents which do not
support peer-to-peer connections. The Mythic documentation for the <code>redirect</code> command gives
an example of using the redirector to tunnel C2 traffic through the agent. This idea can
also be translated to other tools and C2 agents. Empire and meterpreter can be tunneled
through Thanatos to give it p2p functionality.</p>
<p>Since setting up redirectors requires binding to a port on the machine, it is not very
OPSEC safe and may not be practical in restricted environments. This functionality was
designed for lab environments which require a lot of pivoting and lateral movement. I have found when going
through various red team labs that there are machines which cannot directly connect to my
machine. This can make pivoting a little cumbersome by having to use something like
<a href="https://github.com/jpillora/chisel" target="_blank" rel="noopener noreffer ">chisel</a> or SSH port forwarding in order to gain
access to that machine. Having a tool which contains port forwarding capabilities built in (and
eventually socks proxying) makes it more convenient when trying to pivot to other
machines since I do not have to upload chisel binaries or rely on the pivot machine having
SSH available.</p>
<h1 id="future-improvements">Future Improvements</h1>
<p>Future development plans and agent features are mentioned in <a href="https://blog.cybershenanigans.space/posts/thanatos-agent/#future-improvements" rel="">part one</a> of the blog post series.</p>
]]></description></item><item><title>Thanatos: A Mythic C2 Agent Written in Rust</title><link>https://blog.cybershenanigans.space/posts/thanatos-agent/</link><pubDate>Thu, 24 Mar 2022 13:00:00 -0500</pubDate><author>Matt Ehrnschwender</author><guid>https://blog.cybershenanigans.space/posts/thanatos-agent/</guid><description><![CDATA[<p>This is part one of a series of blog posts on Thanatos, a cross-platform Mythic C2 agent written in Rust. This post will go over how the idea for this project came about and why Rust is a great language for offensive tooling development.</p>
<p><a href="/posts/thanatos-agent-usage" rel="">Part two</a> of the series goes over setting it up in an Ubuntu VM and its functionality.</p>
<p>Project repository:
<a href="https://github.com/MythicAgents/thanatos" target="_blank" rel="noopener noreffer ">https://github.com/MythicAgents/thanatos</a></p>
<h1 id="overview">Overview</h1>
<ul>
<li>
<p><a href="#development" rel="">Development</a></p>
<ul>
<li><a href="#background" rel="">Background</a>: Some background on what motivated this project and what this project is</li>
<li><a href="#why-mythic" rel="">Why Mythic?</a>: Advantages of using Mythic for a C2</li>
<li><a href="#mythic-payload-development" rel="">Mythic Payload Development</a>: Development of a Mythic C2 agent</li>
<li><a href="#challenges" rel="">Challenges</a>: Challenges faced during development</li>
</ul>
</li>
<li>
<p><a href="#rust-programming-language" rel="">Rust Programming Language</a></p>
<ul>
<li><a href="#offensive-capabilities" rel="">Offensive Capabilities</a>: Ways Rust is an ideal language for offensive tooling</li>
<li><a href="#transitioning-from-cc-to-rust" rel="">Transitioning from C/C++ to Rust</a>: Transitioning C/C++ concepts to Rust</li>
</ul>
</li>
<li>
<p><a href="#future-improvements" rel="">Future Improvements</a></p>
<ul>
<li><a href="#development-plants" rel="">Development Plans</a>: Future capabilities and development plans</li>
</ul>
</li>
</ul>
<h1 id="development">Development</h1>
<h3 id="background">Background</h3>
<p>Back in early 2021, I was having a discussion with <a href="https://twitter.com/0xdab0" target="_blank" rel="noopener noreffer ">Max Harley</a>, a good friend of mine, about the Rust programming language. At that time, our knowledge of Rust was very limited but we both thought it was a really cool language and had plans of getting more familiar with it. Max decided to pitch the idea of writing a <a href="https://github.com/its-a-feature/Mythic" target="_blank" rel="noopener noreffer ">Mythic</a> agent in Rust as a project for getting more familiar with the language. Due to the ease of cross-compiling Rust code, we also wanted to make the agent cross-platform. This did not seem like a difficult task since the Rust standard library can be compiled for both Linux and Windows without any modifications. Having a native C2 agent which could target both Linux and Windows allows a lot of flexibility due to it not requiring any runtime dependencies such as python or powershell.</p>
<p>So Max and I, with our very minimal knowledge of Rust, decided to start tackling this project of building a C2 agent for Mythic.</p>
<h3 id="why-mythic">Why Mythic?</h3>
<p>There are many C2 frameworks that already exist and include features for developing custom
extensions and modules. Building custom extensions for these frameworks is great; however, I
wanted to build a fully custom agent. There are not any or very few which allow
developing custom fully custom agents. This was very limiting and the other option would be to
develop a C2 framework from scratch for the agent. Writing a custom C2 server for the agent
would mean that I would have to spend development time creating the server architecture
instead of developing only the agent.</p>
<p>Mythic is very unique compared to other frameworks in the sense that it splits up
design and functionality into three distinct parts. These parts are the server, the C2
profiles and the C2 agents. Due to this nature, profiles and agents can be developed
separately from the server and then integrated into the platform. This design for a C2
framework is where Mythic really excels compared to other platforms. Developers have the
freedom to create their own custom agents with unique capabilities for a central server.
This allowed me to only focus on the agent aspects without needing to create my own
custom framework. There are already great examples of the flexibility Mythic brings with
this architecture. The <a href="https://github.com/MythicAgents" target="_blank" rel="noopener noreffer ">MythicAgents</a> Github organization contains a whole
suite of custom agents ranging from fully featured .NET agents to Mac OS JXA agents. On
top of custom C2 agents, there are examples of rather unique C2 profiles. The
<a href="https://github.com/MythicAgents/orthrus" target="_blank" rel="noopener noreffer ">Orthrus</a> agent uses Apple&rsquo;s MDM to backdoor a
Mac OS system and communicates using Apple Push Notifications and the
<a href="https://github.com/MythicAgents/typhon" target="_blank" rel="noopener noreffer ">Typhon</a> agent is a malicious JAMF configuration
which allows Mythic to act as a JAMF server in order to control JAMF enrolled devices. Mythic&rsquo;s
modularity allows for these fully custom payloads and profiles to be developed to work seamlessly with the
Mythic server.</p>
<p>Mythic is the ideal framework for developing custom C2 tools and fits perfectly for my use
case. It provides the flexibility for developing a custom agent without having to focus on
the server aspects. Using Mythic for agent development is ideal when wanting to include
custom payload functionality without creating my own server from scratch. Creating the
server from scratch allows for flexibility on the design of the framework; however, it is not
always viable to create a new framework from scratch.</p>
<h3 id="mythic-payload-development">Mythic Payload Development</h3>
<p>Mythic payload type development is very well documented in the
<a href="https://docs.mythic-c2.net/customizing/payload-type-development" target="_blank" rel="noopener noreffer ">Mythic documentation</a>.
The first stage requires creating a directory structure for the agent.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">.
</span></span><span class="line"><span class="cl">├── agent_icons/
</span></span><span class="line"><span class="cl">│   └── mypayload.svg
</span></span><span class="line"><span class="cl">├── config.json
</span></span><span class="line"><span class="cl">├── documentation-payload/
</span></span><span class="line"><span class="cl">│   └── mypayload/
</span></span><span class="line"><span class="cl">└── Payload_Type/
</span></span><span class="line"><span class="cl">    └── mypayload/
</span></span><span class="line"><span class="cl">        ├── agent_code/
</span></span><span class="line"><span class="cl">        ├── Dockerfile
</span></span><span class="line"><span class="cl">        ├── mythic/
</span></span><span class="line"><span class="cl">        │   ├── agent_functions/
</span></span><span class="line"><span class="cl">        │   │   ├── builder.py
</span></span><span class="line"><span class="cl">        │   │   └── __init__.py
</span></span><span class="line"><span class="cl">        │   ├── browser_scripts/
</span></span><span class="line"><span class="cl">        │   ├── __init__.py
</span></span><span class="line"><span class="cl">        │   ├── mythic_service.py
</span></span><span class="line"><span class="cl">        │   ├── payload_service.sh
</span></span><span class="line"><span class="cl">        │   └── rabbitmq_config.json
</span></span><span class="line"><span class="cl">        └── requirements.txt
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="m">9</span> directories, <span class="m">10</span> files
</span></span></code></pre></div><p>There are a few strict rules when it comes to file and directory names. For example: the
name of the directory under <code>Payload_Type/*</code> has to be the name of the payload. The same
goes for <code>documentation-payload/*</code> for documentation and <code>agent_icons/*.svg</code> for the icon
of the agent. The example above assumes that the agent name is <code>mypayload</code>.</p>
<p>Some of the files such as the <code>mythic_service.py</code> and <code>rabbitmq_config.json</code> file need to
be pre-populated according to the Mythic documentation or other payload types.</p>
<p>The <code>config.json</code> file includes configuration options for the payload.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-JSON" data-lang="JSON"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;exclude_payload_type&#34;</span><span class="p">:</span> <span class="kc">false</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;exclude_c2_profiles&#34;</span><span class="p">:</span> <span class="kc">true</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;exclude_documentation_payload&#34;</span><span class="p">:</span> <span class="kc">false</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;exclude_documentation_c2&#34;</span><span class="p">:</span> <span class="kc">true</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;exclude_documentation_wrapper&#34;</span><span class="p">:</span> <span class="kc">true</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;exclude_agent_icons&#34;</span><span class="p">:</span> <span class="kc">false</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>Since this is only a payload type and doesn&rsquo;t include any custom C2 profiles, only the
<code>exclude_payload_type</code>, <code>exclude_documentation_payload</code> and <code>exclude_agent_icons</code> fields
need to be set to <code>false</code>.</p>
<p>Mythic functions using docker containers. The <code>Payload_Type/mypayload/Dockerfile</code> file is
used to define the docker container the payload builder will use. There are
<a href="https://docs.mythic-c2.net/customizing/payload-type-development#using-the-default-container-base" target="_blank" rel="noopener noreffer ">docker base images</a>
already available which include dependencies for building different types of payloads but
a custom one can be defined. This docker container is used for building the payload; other
functions such as C2 communication are handled in profile containers.</p>
<p>The <code>Payload_Type/mypayload/mythic/agent_functions/builder.py</code> file includes metadata
about the payload along with the implementation for building each payload. The
<a href="https://docs.mythic-c2.net/customizing/payload-type-development/payload-type-info" target="_blank" rel="noopener noreffer ">Mythic documentation</a>
for this file includes a very in-depth guide on what to include in this file in order to
define your agent in Mythic along with how to compile build parameters into the payload.</p>
<p>I like to think of payload type development as containing &ldquo;payload&rdquo; code and &ldquo;mythic&rdquo;
code. The payload code is the code for the agent itself and lives in the
<code>Payload_Type/mypayload/agent_code/</code> directory. The actual development of the agent and
its features occur here. The other part of the agent is the mythic code which is in the
<code>Payload_Type/mypayload/mythic/agent_functions/</code> directory. Here is where various commands
are defined for the agent. This will define the commands and their parameters along with
any other pre-tasking before sending it down to the agent. The system for defining
commands in Mythic provides a vast set of features for the developer. Information about
adding different commands to Mythic can be found in the
<a href="https://docs.mythic-c2.net/customizing/payload-type-development/commands" target="_blank" rel="noopener noreffer ">documentation</a>.</p>
<p>HTTP is a very common C2 communication transport and is one of the easiest to implement.
Mythic already includes an <a href="https://github.com/MythicC2Profiles/http" target="_blank" rel="noopener noreffer ">HTTP C2 profile</a>
which can be used with an agent for C2 communications. This is a fairly straight forward
profile which uses HTTP GET/POST requests and base64 encoded JSON data. The initial check
in for an agent consists of an HTTP request with the following format.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-env" data-lang="env"><span class="line"><span class="cl">Base64<span class="o">(</span> PayloadUUID + JSON<span class="o">({</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;action&#34;</span>: <span class="s2">&#34;checkin&#34;</span>, // required
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;ip&#34;</span>: <span class="s2">&#34;127.0.0.1&#34;</span>, // internal ip address - required
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;os&#34;</span>: <span class="s2">&#34;macOS 10.15&#34;</span>, // os version - required
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;user&#34;</span>: <span class="s2">&#34;its-a-feature&#34;</span>, // username of current user - required
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;host&#34;</span>: <span class="s2">&#34;spooky.local&#34;</span>, // hostname of the computer - required
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;pid&#34;</span>: 4444, // pid of the current process - required
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;uuid&#34;</span>: <span class="s2">&#34;payload uuid&#34;</span>, //uuid of the payload - required
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;architecture&#34;</span>: <span class="s2">&#34;x64&#34;</span>, // platform arch - optional
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;domain&#34;</span>: <span class="s2">&#34;test&#34;</span>, // domain of the host - optional
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;integrity_level&#34;</span>: 3, // integrity level of the process - optional
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;external_ip&#34;</span>: <span class="s2">&#34;8.8.8.8&#34;</span>, // external ip <span class="k">if</span> known - optional
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;encryption_key&#34;</span>: <span class="s2">&#34;base64 of key&#34;</span>, // encryption key - optional
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;decryption_key&#34;</span>: <span class="s2">&#34;base64 of key&#34;</span>, // decryption key - optional
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;process_name&#34;</span>: <span class="s2">&#34;osascript&#34;</span>, // name of the current process - optional
</span></span><span class="line"><span class="cl">    <span class="o">})</span>
</span></span><span class="line"><span class="cl"><span class="o">)</span>
</span></span></code></pre></div><p>The <code>PayloadUUID</code> is generated for each payload at compile time. An HTTP POST request with
this in the body of the request will register an initial check in with Mythic in the
callbacks page. Encryption can be included in the request payload by following the format
specified in the
<a href="https://docs.mythic-c2.net/customizing/c2-related-development/c2-profile-code/agent-side-coding/initial-checkin" target="_blank" rel="noopener noreffer ">documentation</a>.</p>
<p>From here, an agent can be created by periodically beaconing back to the Mythic server to
<a href="https://docs.mythic-c2.net/customizing/c2-related-development/c2-profile-code/agent-side-coding/action_get_tasking" target="_blank" rel="noopener noreffer ">get tasking</a>
and sending the <a href="https://docs.mythic-c2.net/customizing/c2-related-development/c2-profile-code/agent-side-coding/action-post_response" target="_blank" rel="noopener noreffer ">results of completed tasking</a>
back.</p>
<p>This goes over the start of building a basic Mythic payload. Creating more advanced
commands can be found through the Mythic documentation. The example does not go into depth
about all of the other great capabilities included with Mythic. Mythic provides support
for registering new commands with a callback. An example can be where an agent loads a DLL
during runtime and commands with Mythic can be registered in order to interact with that
newly loaded DLL. The <a href="https://github.com/MythicAgents/Medusa" target="_blank" rel="noopener noreffer ">Medusa</a> agent includes this
capability. Mythic also supports a structure for peer-to-peer communications between
agents. An agent can communicate with other agents directly in order to pass on tasking.
The <a href="https://github.com/MythicAgents/Apollo" target="_blank" rel="noopener noreffer ">Apollo</a> and
<a href="https://github.com/MythicAgents/poseidon" target="_blank" rel="noopener noreffer ">Poseidon</a> agents support p2p functionality
through SMB and/or TCP.</p>
<h3 id="challenges">Challenges</h3>
<p>There were a few issues faced when developing the agent. These issues were not necessarily
design issues but were due to how the Rust programming language is designed and what
capabilities I wanted to include into the agent.</p>
<p>The first major issue was compile times. Compiling Rust programs by themselves isn&rsquo;t slow;
however, the way Rust handles compiling and linking dependencies can drastically increase build times.
Dependencies for a Rust project are defined in a <code>Cargo.toml</code> file in the root of the
project directory. When the project is compiled, each dependency is pulled down and then
compiled separately from the main project source and then linked together. Builds are
incremental so once the dependencies are compiled in the project, each subsequent build
will only build the source code for the main project and link the built dependencies. An
initial build of a project may take around 40 seconds to download and compile all of the
dependencies whereas subsequent builds only take around 0.3 seconds. This dependency
management system works very well; however, it is per-project. If you have two Rust
projects that both rely on the same library, each project will compile the library and
store the built library in their project directory. On top of this, dependencies will also
be built according to what target the project is building for. If a project was built for
64 bit Linux, a subsequent 32 bit Linux build will require rebuilding all of the
dependencies for 32 bit.</p>
<p>How does this relate to Thanatos? Initially, Thanatos would not do any special dependency
caching. This meant that each time a new payload was built, the dependencies for the
payload were compiled each time. Build times would average around 30 seconds to a minute
each build depending on system resources. To solve this issue, the payload builder will
cache dependencies after the first build for the target platform. An initial build of
a Linux 64 bit payload will compile all of the dependencies for 64 bit Linux and then
cache them for future builds. This allows for the build times of subsequent builds to be
significantly reduced. This design was used to help reduce the size of the docker image.
The docker image could already include pre-built dependencies but that would mean there
would need to be Windows/Linux 64 and 32 bit targets along with statically linked Linux
builds. If an operation does not require Linux agents, then the libraries would take up a
lot of unnecessary hard drive space.</p>
<p>The second issue was cross-compilation. Rust by itself has incredible cross-compilation
capabilities; however, those can be affected when introducing dependencies which require C
development libraries. The ssh2 library that Thanatos uses for SSH requires openssl. When
compiling for Windows targets, an openssl library compatible with mingw is needed. There
also needs to include both 32 bit and 64 bit builds. One of my options to fix this was by
cross-compiling openssl for each platform I needed and then including that inside the
docker container. It wasn&rsquo;t an ideal fix for the issue but it would make the agent
compile. I found out that the Fedora docker base image included all of the dependencies I
needed inside the repositories so I ended up using Fedora for the docker base image.</p>
<p>One of the other influencers for using Fedora for the docker base image was due to Windows
32 bit builds. I was having a fair bit of difficulty getting Windows 32 bit Rust binaries
built in Ubuntu docker containers which I tracked down to being an issue with the
mingw32 compiler included in the Ubuntu repository. The mingw32 compiler in the Ubuntu repositories
comes with an option compiled in which uses a linker not compatible with Rust&rsquo;s libunwind. This
was a major hindrance which meant that Thanatos could not target Windows 32 bit platforms.
Building 32 bit Windows binaries would allow for injecting the payload into 32 bit
processes so it would be a nice feature to include. Luckily, the mingw32 compiler in Fedora
did not enable this feature and allowed building 32 bit Windows payloads.</p>
<h1 id="rust-programming-language">Rust Programming Language</h1>
<h3 id="offensive-capabilities">Offensive Capabilities</h3>
<p>Digging more into Rust, I was blown away by the offensive capabilities it can provide.
Rust can be thought of, at a high level, as a language which bridges the gap between
low-level systems development through direct memory manipulation and high-level
development such as manipulating JSON. Rust has the ability to work with raw pointers and
manipulate memory very similar to C/C++. There may be times where a DLL needs to be loaded
reflectively in either the current process or another process. Rust can parse the DLL
headers and resolve all the symbols in the same way that C/C++ can. Reflectively loading a
DLL means that the DLL does not touch the hard disk of the target system which can trigger
AV or EDR depending on what the DLL is. Rust even supports inline assembly. This allows
offensive tool developers very fine control over what executes in their program. Golang
can use pointers but they don&rsquo;t provide the same level of control as Rust. Golang gets
around this by writing the low-level memory code in C and then using the Golang C ffi to
invoke those C functions. Rust does not need to rely on C for any low-level memory
management.</p>
<p>As mentioned, Rust is used for bridging the gap between low-level systems development and
high-level development. Working with JSON Rust using the
<a href="https://docs.serde.rs/serde_json/" target="_blank" rel="noopener noreffer ">serde_json</a> library is very similar to working with JSON in
Golang. There are many different <a href="https://lib.rs/web-programming/http-client" target="_blank" rel="noopener noreffer ">HTTP libraries</a> available with many including async
support. Using an HTTP library such as <code>reqwest</code> makes sending HTTP requests and returning
the output as simple as</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-Cargo.toml" data-lang="Cargo.toml"><span class="line"><span class="cl"><span class="p">[</span><span class="nx">dependencies</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="nx">reqwest</span> <span class="p">=</span> <span class="p">{</span> <span class="nx">version</span> <span class="p">=</span> <span class="s2">&#34;0.11&#34;</span><span class="p">,</span> <span class="nx">features</span> <span class="p">=</span> <span class="p">[</span><span class="s2">&#34;blocking&#34;</span><span class="p">]</span> <span class="p">}</span>
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-src/main.rs" data-lang="src/main.rs"><span class="line"><span class="cl"><span class="k">fn</span> <span class="nf">main</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="n">data</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">reqwest</span>::<span class="n">blocking</span>::<span class="n">get</span><span class="p">(</span><span class="s">&#34;http://example.com&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">.</span><span class="n">unwrap</span><span class="p">()</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">.</span><span class="n">text</span><span class="p">()</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">.</span><span class="n">unwrap</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="fm">println!</span><span class="p">(</span><span class="s">&#34;</span><span class="si">{}</span><span class="s">&#34;</span><span class="p">,</span><span class="w"> </span><span class="n">data</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>No need to initialize an HTTP handle or manually allocate memory.</p>
<p>Libraries not only make the development process easier but the language provides various
functional features which can help reduce the amount of code needed to do various tasks.
The standard library is very extensive and almost always includes some way of doing a very
specific task in an elegant manner.</p>
<p>A few great resources on Rust being used for offensive tooling worth checking out are
<a href="https://kerkour.com/black-hat-rust" target="_blank" rel="noopener noreffer ">Black Hat Rust</a> and
<a href="https://github.com/trickster0/OffensiveRust" target="_blank" rel="noopener noreffer ">Offensive Rust</a>.</p>
<h3 id="transitioning-from-cc-to-rust">Transitioning From C/C++ to Rust</h3>
<p>There have been many situations I have found where I can ditch C/C++ for a project and use
Rust instead. Rust can do anything I need which C/C++ can do while also bringing memory
safety. C and C++ have a history of being the root cause for many different memory
corruption vulnerabilities that exist even today. This is partly due to the developers
writing software which contains bugs and partly due to the fact that C/C++ do not prevent
people from writing software which could introduce a memory corruption vulnerability.</p>
<p>This is why Rust is a great language for C/C++ developers who want to write secure code
while keeping the same performance and low-level properties of C/C++. There are a few
things that tripped me up when transitioning from C/++ to Rust.</p>
<p>The Rust compiler features a borrow checker which can be a little frustrating to get used
to at first. The idea behind the borrow checker is to prevent pointer aliasing and shared
mutability. Here are two examples to demonstrate ownership and borrowing.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-Rust" data-lang="Rust"><span class="line"><span class="cl"><span class="k">fn</span> <span class="nf">main</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">&#34;Hello World&#34;</span><span class="p">.</span><span class="n">to_string</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="n">b</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">a</span><span class="p">;</span><span class="w"> </span><span class="c1">// &#39;a&#39; variable is moved to &#39;b&#39;
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="fm">println!</span><span class="p">(</span><span class="s">&#34;</span><span class="si">{}</span><span class="s">&#34;</span><span class="p">,</span><span class="w"> </span><span class="n">a</span><span class="p">);</span><span class="w"> </span><span class="c1">// since &#39;a&#39; was moved to &#39;b&#39;, &#39;a&#39; is no longer valid
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>This example will not compile. The <code>a</code> variable contains a heap allocated string <code>&quot;Hello World&quot;</code>. The <code>b</code> variable is now being assigned to the <code>a</code> variable and the <code>a</code> variable
is being printed out. C/C++ will treat <code>a</code> and <code>b</code> as pointers to the same heap allocated
string <code>&quot;Hello World&quot;</code>. This results in <code>a</code> and <code>b</code> pointing to the same area of memory
which can result in unsafe behavior. Other languages such as Golang or Python will make a
copy of the string whenever it gets assigned to the <code>b</code> variable. Since heap allocations
can be relatively expensive computationally, Rust won&rsquo;t implicitly allocate memory and
store a new copy of the string but instead throw a compile error.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-Rust" data-lang="Rust"><span class="line"><span class="cl"><span class="k">fn</span> <span class="nf">main</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">&#34;Hello World&#34;</span><span class="p">.</span><span class="n">to_string</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="n">b</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="o">&amp;</span><span class="n">a</span><span class="p">;</span><span class="w"> </span><span class="c1">// &#39;b&#39; is now a reference to &#39;a&#39;
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="fm">println!</span><span class="p">(</span><span class="s">&#34;</span><span class="si">{}</span><span class="s">&#34;</span><span class="p">,</span><span class="w"> </span><span class="n">a</span><span class="p">);</span><span class="w"> </span><span class="c1">// Since &#39;b&#39; is a reference to &#39;a&#39;, &#39;a&#39; is still valid
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>This example does compile because the ownership of the heap allocation containing the string
<code>&quot;Hello World&quot;</code> isn&rsquo;t being passed to the <code>b</code> variable but instead, <code>b</code> is now borrowing
the string from <code>a</code>. This may seem like a basic concept; however, it can become very
tedious when applying it.</p>
<p>Lifetimes exist in C/C++ but they are more verbose in Rust. Lifetimes are the idea that
when a variable refers to another piece of data, that data will exist in the program as
long as any references to that variable. Lifetimes in Rust can get a little bit ugly but
knowing how and when to use them can help make them easier to read.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-Rust" data-lang="Rust"><span class="line"><span class="cl"><span class="k">fn</span> <span class="nf">main</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="n">a</span>: <span class="nb">String</span> <span class="o">=</span><span class="w"> </span><span class="s">&#34;Hello World&#34;</span><span class="p">.</span><span class="n">to_string</span><span class="p">();</span><span class="w"> </span><span class="c1">// &#34;Hello World&#34; is a heap allocated string
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="n">b</span>: <span class="kp">&amp;</span><span class="kt">str</span> <span class="o">=</span><span class="w"> </span><span class="n">a</span><span class="p">.</span><span class="n">as_str</span><span class="p">();</span><span class="w"> </span><span class="c1">// refers to the heap allocated string directly
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="fm">println!</span><span class="p">(</span><span class="s">&#34;</span><span class="si">{}</span><span class="s">&#34;</span><span class="p">,</span><span class="w"> </span><span class="n">b</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>I included types for the variables to make the program logic a little easier to understand. The <code>b</code>
variable refers to the <code>&quot;Hello World&quot;</code> string by reference. This is valid but what happens
if the <code>&quot;Hello World&quot;</code> string gets deallocated?</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-Rust" data-lang="Rust"><span class="line"><span class="cl"><span class="k">fn</span> <span class="nf">main</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="n">a</span>: <span class="nb">String</span> <span class="o">=</span><span class="w"> </span><span class="s">&#34;Hello World&#34;</span><span class="p">.</span><span class="n">to_string</span><span class="p">();</span><span class="w"> </span><span class="c1">// &#34;Hello World&#34; is a heap allocated string
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="n">b</span>: <span class="kp">&amp;</span><span class="kt">str</span> <span class="o">=</span><span class="w"> </span><span class="n">a</span><span class="p">.</span><span class="n">as_str</span><span class="p">();</span><span class="w"> </span><span class="c1">// refers to the heap allocated string directly
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nb">drop</span><span class="p">(</span><span class="n">a</span><span class="p">);</span><span class="w"> </span><span class="c1">// Deallocate the &#34;Hello World&#34; string
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="fm">println!</span><span class="p">(</span><span class="s">&#34;</span><span class="si">{}</span><span class="s">&#34;</span><span class="p">,</span><span class="w"> </span><span class="n">b</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>This obviously won&rsquo;t work because <code>b</code> is now a reference to memory which was deallocated.
Lifetime issues become clearer when working with structures.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-Rust" data-lang="Rust"><span class="line"><span class="cl"><span class="k">struct</span> <span class="nc">MyStruct</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">field1</span>: <span class="kp">&amp;</span><span class="kt">str</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="k">fn</span> <span class="nf">main</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="n">b</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">&#34;Hello World&#34;</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">MyStruct</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="n">field1</span>: <span class="s">&#34;Hello World&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="p">};</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="fm">println!</span><span class="p">(</span><span class="s">&#34;</span><span class="si">{}</span><span class="s">&#34;</span><span class="p">,</span><span class="w"> </span><span class="n">a</span><span class="p">.</span><span class="n">field1</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>This example won&rsquo;t compile because it is not guaranteed that every time <code>MyStruct</code> is
created the string <code>field1</code> refers to will be valid. <code>&amp;str</code> can be thought of as a string
literal and not a heap allocated string. This is where a lifetime parameter is needed.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-Rust" data-lang="Rust"><span class="line"><span class="cl"><span class="k">struct</span> <span class="nc">MyStruct</span><span class="o">&lt;</span><span class="na">&#39;a</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">field1</span>: <span class="kp">&amp;</span><span class="na">&#39;a</span> <span class="kt">str</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="k">fn</span> <span class="nf">main</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="n">b</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">&#34;Hello World&#34;</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">MyStruct</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="n">field1</span>: <span class="nc">b</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="p">};</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="fm">println!</span><span class="p">(</span><span class="s">&#34;</span><span class="si">{}</span><span class="s">&#34;</span><span class="p">,</span><span class="w"> </span><span class="n">a</span><span class="p">.</span><span class="n">field1</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>This does compile because the <code>'a</code> lifetime sends a hint to the compiler that any value
which <code>field1</code> refers to has to live as long as the structure itself.</p>
<h1 id="future-improvements">Future Improvements</h1>
<h3 id="development-plans">Development Plans</h3>
<p>The agent is far from finished and development will continue to happen. This initial release should
be thought of as a beta test for the agent to see what areas could be improved and to fix
any potential bugs. The agent hasn&rsquo;t been thoroughly tested so there are most-likely
issues that will arise. New feature development is going to focus on areas which have a potential of affecting the
overall structure of the agent. The reasoning behind this is due to the potential of having
to rewrite the agent, or most of it, to include a certain feature. Rewriting the agent
would not be a huge setback now; however, if miscellaneous features are added before the
structure isn&rsquo;t solidified, a rewrite would take a lot more time.</p>
<p>The three most important features which could potentially require restructuring the code
base of the agent are: integration of multiple C2 profiles, socks proxying through the
agent and p2p C2 profiles. Once the overall structure of the agent is completely figured
out, it should make adding various commands a matter of implementing the code which
accomplishes the task.</p>
]]></description></item></channel></rss>