<epigraph>
  <attribution>Arthur C. Clarke</attribution>
  <simpara>
    Any sufficiently advanced technology is indistinguishable from magic.
  </simpara>
</epigraph>

<simpara>
  Building executables from C source code is a complex task.
  An innocent looking call of
  <citerefentry>
    <refentrytitle>gcc</refentrytitle>
    <manvolnum>1</manvolnum>
  </citerefentry> will invoke a pre-processor, a multi-pass compiler,
  an assembler and finally a linker.
  Using all these tools to plant virus code into another executable
  makes the result either prohibitively large, or very dependent on
  the completeness of the target installation.
</simpara>
<simpara>
  Real viruses approach the problem from the other end. They are
  aggressively optimized for code size and do only what's absolutely
  necessary. Basically they just copy one chunk of code and patch a few
  addresses at hard coded offsets.
</simpara>
<para>
  However, this has drastic effects:
  <itemizedlist>
    <listitem>
      <simpara>
	Since we directly copy binary code, the virus is restricted
	to a particular hardware architecture.
      </simpara>
    </listitem>
    <listitem>
      <simpara>
        Code must be position independent.
      </simpara>
    </listitem>
    <listitem>
      <simpara>
        Code cannot use shared libraries; not even the C runtime library.
      </simpara>
    </listitem>
    <listitem>
      <simpara>
        We cannot allocate global variables in the data segment.
      </simpara>
    </listitem>
  </itemizedlist>
</para>
<simpara>
  There are ways to circumvent these limitations. But they are
  complicated and make the virus more likely to fail.
</simpara>

<sect2 id="executable.and.linkable.format"
  xreflabel="Executable and linkable format">
  <title>Executable and linkable format</title>

  <simpara>
    Another natural limitation of viruses is rigid dependency on the
    file format of target executables. These formats differ a lot.
    Even on the same hardware architecture and under the same
    operating system. Furthermore executable are not designed with
    post link-time modifications in mind. It's rare for a virus to
    support more than one infection method. This document is about
    the format used on recent versions of Linux, FreeBSD and Solaris.
  </simpara>

  <simplesect id="ELF.specification" xreflabel="ELF specification">
    <title>ELF specification</title>

    <simpara>This format is well documented. Some public resources:</simpara>
    <itemizedlist>
      <listitem><simpara>
	Source code of Linux and FreeBSD.
	Admittedly not for the faint of heart.
      </simpara></listitem> 
      <listitem><simpara>
	<filename>/usr/include/elf.h</filename>
	<footnote><simpara>
	  Present on Linux (part of glibc) and FreeBSD.
	</simpara></footnote>
      </simpara></listitem> 
      <listitem><simpara>
	Portable Formats Specification, Version 1.1.
	<footnote>
	  <simplelist>
	    <member>Canonical Postscript document:
	      &url.elf.spec.canonical;</member>
	    <member>A flat-text version:
	      &url.elf.spec.flat.text;</member>
	  </simplelist>
	</footnote>
      </simpara></listitem> 
      <listitem><simpara>
	Creating Really Teensy ELF Executables for Linux
	&note.teensy.executables;
      </simpara></listitem> 
    </itemizedlist>

    <simpara>A quote from the Portable Formats Specification:</simpara>
    <blockquote>
      <simpara>
	The Executable and Linking Format was originally developed
	and published by UNIX System Laboratories (USL) as part of
	the Application Binary Interface (ABI). The Tool Interface
	Standards committee (TIS) has selected the evolving
	<acronym>ELF</acronym> standard as a portable object file
	format that works on 32-bit Intel Architecture environments
	for a variety of operating systems.
      </simpara>
    </blockquote>

  </simplesect>
  <simplesect id="assembly.documentation">
    <title>Assembly language documentation</title>

    <simpara>
      Actually <acronym>ELF</acronym> is defined for a variety of
      both 32 bit and 64 bit architectures. Obviously you need to
      handle assembly language for each platform. A good starting
      point is <quote>Linux Assembly</quote> &note.linuxassembly;
      and <quote>Assembly Language Related Web Sites</quote>.
      &note.raymoon.assembly;
    </simpara>

    <simpara>i386 specific sites:</simpara>
    <itemizedlist>
      <listitem><simpara>
        Assembly-HOWTO. &note.HOWTO.assembly;
	Description of tools and sites for Linux.
      </simpara></listitem> 
      <listitem><simpara>
        FAQ of comp.lang.asm.x86 &note.faq.x86;
      </simpara></listitem> 
      <listitem><simpara>
	<quote>Robin Miyagi's Linux Programming</quote>
	&note.robin.miyagi; features a tutorial and interesting links.
      </simpara></listitem> 
      <listitem><simpara>
	<quote>Assembly resources</quote> &note.agner.org;
	covers advanced topics.
      </simpara></listitem> 
      <listitem><simpara>
        IA-32 Intel Architecture Software Developer's Manual
        &note.intel.pentium4;
      </simpara></listitem> 
      <listitem><simpara>
	<quote>The Place on the Net to Learn Assembly Language
	  Programming</quote> &note.webster.assembly;
      </simpara></listitem> 
      <listitem><simpara>
        The Art of Assembly Language. 32-bit Linux Edition
	Featuring HLA. &note.art.of.assembly;
      </simpara></listitem> 
      <listitem><simpara>
        X86 Architecture, low-level programming, freeware
	&note.goosee.assembly;
      </simpara></listitem> 
      <listitem><simpara>
        Dr. Dobb's Microprocessor Resources &note.dobbs.assembly;
      </simpara></listitem> 
    </itemizedlist>

    <simpara>sparc specific sites:</simpara>
    <itemizedlist>
      <listitem><simpara>
        SPARC Assembly Language Reference Manual
	&note.sun.sparc.assembly;
      </simpara></listitem> 
      <listitem><simpara>
        A Laboratory Manual for the SPARC
	&note.maccabe.sparc.assembly;
      </simpara></listitem> 
    </itemizedlist>
  </simplesect>

</sect2>
<sect2>
  <title>Portability</title>

  <simpara>
    This document tries to cover multiple platforms
    through conditional compilation. There is a
    <filename>configure.pl</filename> that determines the host type
    and sets up a <filename>Makefile</filename>.
    The <filename>Makefile</filename> uses individual sub-directories
    for each platform and exports the name of these directories
    (and some other platform specific values) as environment variables.
    Most of the shell scripts invoked by
    <citerefentry>
      <refentrytitle>make</refentrytitle>
      <manvolnum>1</manvolnum>
    </citerefentry> are shown here.
    The following table should help to understand them.
  </simpara>

  <table frame="none" pgwide="1">
    <title>Environment variables exported by Makefile</title>
    <tgroup cols="2">
      <thead>
	<row>
	  <entry>Variable</entry>
	  <entry>Value on this platform</entry>
	</row>
      </thead>
      <tbody>
	<row><entry>${ARCH}</entry><entry>&config.ARCH;</entry></row>
	<row><entry>${CFLAGS}</entry><entry>&config.CFLAGS;</entry></row>
	<row>
	  <entry>${ELF_BASE}</entry>
	  <entry>&config.ELF.BASE;</entry>
	</row>
	<row>
	  <entry>${ELF_ALIGN}</entry>
	  <entry>&config.ELF.ALIGN;</entry>
	</row>
	<row><entry>${OUT}</entry><entry>&config.OUT;</entry></row>
	<row><entry>${TMP}</entry><entry>&config.TMP;</entry></row>
      </tbody>
    </tgroup>
  </table>

</sect2>
<sect2 id="in.the.language.of.mortals"
  xreflabel="In the language of mortals">
  <title>In the language of mortals</title>

  <simpara>
    For the first example I'll present the simplest piece of code that
    still gives sufficient feedback. Our aim is to implant it into
    <filename>/bin/sh</filename>.
    On practically every recent installation of &config.HOSTTYPE; the
    following code will emit three magic letters instead of just
    dumping core.
  </simpara>

  <formalpara>
    <title>Source: &config.OUT;/magic_elf/magic_elf.c</title>
    <para>
      <programlisting><inlinemediaobject><imageobject><imagedata
	format="linespecific"
	fileref="../&config.OUT;/magic_elf/magic_elf.c"
      /></imageobject></inlinemediaobject></programlisting>
    </para>
  </formalpara>

  <simpara>
    It is not an error that a file called
    <filename>magic_elf.c</filename> is located
    in a directory called <filename>&config.OUT;</filename>.
    The <filename>Makefile</filename> building this document
    did trivial pre-processing on the original source file.
    <acronym>ELF</acronym> is used on many architectures.
    And each has a different magic value.
  </simpara>

  <formalpara>
    <title>Command: src/magic_elf/cc.sh</title>
    <para>
      <programlisting><inlinemediaobject><imageobject><imagedata
        format="linespecific"
	fileref="../src/magic_elf/cc.sh"
      /></imageobject></inlinemediaobject></programlisting
    ></para>
  </formalpara>
  <formalpara>
    <title>Output: &config.OUT;/magic_elf/magic_elf</title>
    <para>
      <programlisting><inlinemediaobject><imageobject><imagedata
        format="linespecific"
	fileref="../&config.OUT;/magic_elf/magic_elf"
      /></imageobject></inlinemediaobject></programlisting
    ></para>
  </formalpara>

</sect2>
<sect2 id="how.it.works" xreflabel="How it works">
  <title>How it works</title>

  <sect3>
    <title>Digested answer</title>
    <simpara>
      The three letters are part of the signature of
      <acronym>ELF</acronym> files. Executables created by
      <citerefentry>
	<refentrytitle>ld</refentrytitle>
	<manvolnum>1</manvolnum>
      </citerefentry> are always mapped into the same memory region.
      That's why the program can find its own header at a predictable
      virtual address.
    </simpara>
  </sect3>

  <sect3>
    <title>Short answer</title>
    <simpara>
      RTFM. &note.jargon.RTFM;
      Just read all of <xref linkend="ELF.specification"/>.
    </simpara>
  </sect3>

  <sect3 id="sort.of.an.answer" xreflabel="Sort of an answer">
    <title>Sort of an answer</title>
    <simpara>
      <constant>&calc.base.addr;</constant> is not a natural constant,
      but happens to be the default base address of
      <acronym>ELF</acronym> executables produced by
      <citerefentry>
	<refentrytitle>ld</refentrytitle>
	<manvolnum>1</manvolnum>
      </citerefentry>.
      As of version 2.11 of <application>binutils</application> it
      should be possible to change that with options
      <option>-Ttext ORG</option> and
      <option>--section-start SECTIONNAME=ORG</option>, but I didn't
      get it working. Anyway, the layout of executables produced by
      <citerefentry>
	<refentrytitle>ld</refentrytitle>
	<manvolnum>1</manvolnum>
      </citerefentry> is straight forward.
    </simpara>
    <orderedlist>
      <listitem><simpara>
	One <acronym>ELF</acronym> header -
	<structname>Elf32_Ehdr</structname>
      </simpara></listitem><listitem><simpara>
	Program headers - <structname>Elf32_Phdr</structname>
      </simpara></listitem><listitem><simpara>
	Program interpreter (not if statically linked)
      </simpara></listitem><listitem><simpara>
	Code
      </simpara></listitem><listitem><simpara>
	Data
      </simpara></listitem><listitem><simpara>
	Section headers - <structname>Elf32_Shdr</structname>
      </simpara></listitem>
    </orderedlist>
    <simpara>
      Everything from the start of the file to the last byte of code
      is mapped into one segment (named <quote>code</quote> or
      <quote>text</quote>) that begins at the base address.
      There is a whole chapter called
      <xref linkend="readelf" endterm="readelf"/> describing a command
      to view all these details.
      In the meantime I will show fancy ways to get by without.
    </simpara>
  </sect3>

</sect2>
<sect2>
  <title>Strings and dumps</title>

  <simpara>
    What would you do if you knew nothing about <acronym>ELF</acronym>
    and just asked yourself how that example works? How can you go sure
    that the executable file really contains those three letters?
  </simpara>
  <simpara>
    A good start for finding text in binary files is
    <citerefentry>
      <refentrytitle>strings</refentrytitle>
      <manvolnum>1</manvolnum>
    </citerefentry>.
  </simpara>
  <formalpara>
    <title>Command: src/magic_elf/strings.sh</title>
    <para>
      <programlisting><inlinemediaobject><imageobject><imagedata
        format="linespecific"
	fileref="../src/magic_elf/strings.sh"
      /></imageobject></inlinemediaobject></programlisting>
    </para>
  </formalpara>
  <formalpara>
    <title>Output: &config.OUT;/magic_elf/strings</title>
    <para>
      <programlisting><inlinemediaobject><imageobject><imagedata
        format="linespecific"
	fileref="../&config.OUT;/magic_elf/strings"
      /></imageobject></inlinemediaobject></programlisting>
    </para>
  </formalpara>
  <simpara>
    The leading <literal>1:</literal> is written by
    <citerefentry>
      <refentrytitle>grep</refentrytitle>
      <manvolnum>1</manvolnum>
    </citerefentry>
    and tells that our three-letter word is the first found string.
    This gives some help where we can find it in a hex dump. 
    It is difficult to search strings in such a dump because of
    line breaks. Interactive tools like
    <citerefentry>
      <refentrytitle>hexedit</refentrytitle>
      <manvolnum>1</manvolnum>
    </citerefentry> or
    <citerefentry>
      <refentrytitle>hexedit</refentrytitle>
      <manvolnum>1</manvolnum>
    </citerefentry> might be useful.
  </simpara>
  <simpara>
    The traditional tool for dumps is
    <citerefentry>
      <refentrytitle>od</refentrytitle>
      <manvolnum>1</manvolnum>
    </citerefentry>. Its name is probably an abbreviation for
    <quote>octal dump</quote>. <application>GNU od</application>
    provides <option>-t x1</option> for byte wise hexadecimal output. 
    We stick to the standard options.
  </simpara>
  <formalpara>
    <title>Command: src/magic_elf/od.sh</title>
    <para>
      <programlisting><inlinemediaobject><imageobject><imagedata
        format="linespecific"
	fileref="../src/magic_elf/od.sh"
      /></imageobject></inlinemediaobject></programlisting>
    </para>
  </formalpara>
  <formalpara>
    <title>Output: &config.OUT;/magic_elf/od</title>
    <para>
      <programlisting><inlinemediaobject><imageobject><imagedata
        format="linespecific"
	fileref="../&config.OUT;/magic_elf/od"
      /></imageobject></inlinemediaobject></programlisting>
    </para>
  </formalpara>

  <simpara>
    <citerefentry>
      <refentrytitle>hexdump</refentrytitle>
      <manvolnum>1</manvolnum>
    </citerefentry> is part of util-linux but also available on FreeBSD.
    It features user defined formats.
  </simpara>
  <formalpara>
    <title>Source: src/format.hex</title>
    <para>
      <programlisting><inlinemediaobject><imageobject><imagedata
        format="linespecific"
	fileref="../src/format.hex"
      /></imageobject></inlinemediaobject></programlisting>
    </para>
  </formalpara>
  <formalpara>
    <title>Source: src/magic_elf/hexdump.sh</title>
    <para>
      <programlisting><inlinemediaobject><imageobject><imagedata
        format="linespecific"
	fileref="../src/magic_elf/hexdump.sh"
      /></imageobject></inlinemediaobject></programlisting>
    </para>
  </formalpara>
  <formalpara>
    <title>Source: &config.OUT;/magic_elf/hexdump</title>
    <para>
      <programlisting><inlinemediaobject><imageobject><imagedata
        format="linespecific"
	fileref="../&config.OUT;/magic_elf/hexdump"
      /></imageobject></inlinemediaobject></programlisting>
    </para>
  </formalpara>

  <simpara>
    At this point we can guess that file offset 1 and
    <literal>&calc.base.addr; + 1</literal> are not coincidental.
    A test program might help.
  </simpara>

</sect2>
<sect2 id="address.of.main" xreflabel="The address of main">
  <title>The address of main</title>

  <formalpara>
    <title>Source: &config.OUT;/magic_elf/addr_of_main.c</title>
    <para>
      <programlisting><inlinemediaobject><imageobject><imagedata
        format="linespecific"
	fileref="../&config.OUT;/magic_elf/addr_of_main.c"
      /></imageobject></inlinemediaobject></programlisting>
    </para>
  </formalpara>
  <formalpara>
    <title>Output: &config.OUT;/magic_elf/addr_of_main</title>
    <para>
      <programlisting><inlinemediaobject><imageobject><imagedata
        format="linespecific"
	fileref="../&config.OUT;/magic_elf/addr_of_main"
      /></imageobject></inlinemediaobject></programlisting>
    </para>
  </formalpara>
  <simpara>
    Looks good. The byte at address <literal>&calc.base.addr; + 0</literal>
    is equal to that at file offset 0. And &calc.magic.elf.addr.main.X;
    is a plausible address of function <function>main</function>.
  </simpara>

</sect2>
<sect2>
  <title>Other roads to <acronym>ELF</acronym></title>

  <formalpara>
    <title>Source: &config.OUT;/magic_elf/other_perl.pl</title>
    <para>
      <programlisting><inlinemediaobject><imageobject><imagedata
        format="linespecific"
	fileref="../&config.OUT;/magic_elf/other_perl.pl"
      /></imageobject></inlinemediaobject></programlisting>
    </para>
  </formalpara>
  <formalpara>
    <title>Output: &config.OUT;/magic_elf/other_perl</title>
    <para>
      <programlisting><inlinemediaobject><imageobject><imagedata
        format="linespecific"
	fileref="../&config.OUT;/magic_elf/other_perl"
      /></imageobject></inlinemediaobject></programlisting>
    </para>
  </formalpara>

  &config.xml.other.magic;
      
</sect2>
