<epigraph>
  <attribution>Groucho Marx</attribution>
  <simpara>
    Outside of a dog, a book is a man's best friend.
    Inside a dog it's too dark to read.
  </simpara>
</epigraph>

<simpara>
  Let's get a bit more serious and examine the assembly program from
  <xref linkend="the.language.of.evil"> with
  <citerefentry>
    <refentrytitle>readelf</refentrytitle>
    <manvolnum>1</manvolnum>
  </citerefentry>, part of the <application>binutils</application>
  package.  This tool is huge. Here we use only one option,
  <option>-l</option>.
</simpara>

<formalpara>
  <title>Command: src/readelf/evil_magic.sh</title>  <para>
    <programlisting><inlinemediaobject><imageobject><imagedata
      format="linespecific"
      fileref="../src/readelf/evil_magic.sh"
    ></imageobject></inlinemediaobject></programlisting>
  </para>
</formalpara>
<formalpara>
  <title>Output: out/i386/readelf/evil_magic</title>  <para>
    <programlisting><inlinemediaobject><imageobject><imagedata
      format="linespecific"
      fileref="../out/i386/readelf/evil_magic"
    ></imageobject></inlinemediaobject></programlisting>
  </para>
</formalpara>

<para>
  Nice to see the <link linkend="enter.evil">entry point</link> 
  we retrieved through
  <citerefentry>
    <refentrytitle>od</refentrytitle>
    <manvolnum>1</manvolnum>
  </citerefentry> again.
  Program layout is a simplified variation of
  <xref linkend="sort.of.an.answer">.
  The value of <literal>FileSiz</literal> includes
  <acronym>ELF</acronym> header and program header.
  The size of this overhead is:
  <blockquote>
    <para>
      overhead =
      <literal>Entry point</literal> - <literal>VirtAddr</literal> =
      &calc.evil.magic.start.X; - &calc.base.addr; =
      &calc.evil.magic.ofs.X; = &calc.evil.magic.ofs.D bytes
    </para>
  </blockquote>

  So effective code size is:
  <blockquote>
    <para>
      code size =
      <literal>FileSiz</literal> - overhead =
      &calc.evil.magic.LOAD1.filesiz.X; -
      &calc.evil.magic.ofs.X; =
      &calc.evil.magic.codesize.X; =
      &calc.evil.magic.codesize.D;
      bytes
    </para>
  </blockquote>

  This matches with the
  <link linkend="evil.magic.revealed">disassembly listing</link>.
  However, the ratio of file size to effective code deserves the title
  <quote>Bloat</quote>, with capital B.
  <blockquote>
    <para>
      code size / file size =
      &calc.evil.magic.codesize.D; /
      &calc.evil.magic.size.D; =
      &calc.evil.magic.bloat;
    </para>
  </blockquote>

  Only &calc.evil.magic.bloat.percent; percent of the file actually
  do something useful!
</para>

<simpara>
  Anyway, we see that even for trivial examples the code is surrounded
  by lots of other stuff. Let's zoom in on our target.
</simpara>

<sect2 id="bashful.glance" xreflabel="Bashful glance">
  <title>Bashful glance</title>

  <formalpara>
    <title>Command: src/readelf/segments.sh</title>    <para>
      <programlisting><inlinemediaobject><imageobject><imagedata
        format="linespecific"
	fileref="../src/readelf/segments.sh"
      ></imageobject></inlinemediaobject></programlisting>
    </para>
  </formalpara>
  <formalpara>
    <title>Output: out/i386/readelf/segments</title>    <para>
      <programlisting><inlinemediaobject><imageobject><imagedata
        format="linespecific"
	fileref="../out/i386/readelf/segments"
      ></imageobject></inlinemediaobject></programlisting>
    </para>
  </formalpara>

  <simpara>
    Looks intimidating. But then the <acronym>ELF</acronym> specification
    says that only segments of type <quote>LOAD</quote> are considered for
    execution. Since the flags of the first one are <literal>R E</literal>,
    meaning <quote>read &amp; execute</quote>, we know that it must be the
    code segment. The other one has <literal>RW</literal>, meaning
    <quote>read &amp; write</quote>, so it must be the data segment.
  </simpara>
  <simpara>
    
  </simpara>
  <simpara>
    <literal>MemSiz</literal> is larger than <literal>FileSiz</literal>
    in the data segment. Just like with
    <citerefentry>
      <refentrytitle>mmap</refentrytitle>
      <manvolnum>2</manvolnum>
    </citerefentry>
    excessive bytes are defined to be initialized with 0.
    The linker takes advantages of that by grouping all variables
    that should be initialized to zero at the end. Note that the last
    section of segment 3 (counting starts with 0) is called
    <literal>.bss</literal>, the traditional name for this kind of area.
  </simpara>
  <simpara>
    The mapping for segment 2 looks even more complex. But I would guess
    that <literal>.rodata</literal> means <quote>read-only data</quote>
    and <literal>.text</literal> contains productive code, as opposed
    to the administrative stuff in the other sections.
  </simpara>

</sect2>
<sect2 id="turn.the.pages" xreflabel="Turn the pages">
  <title>Turn the pages</title>

  <para>
    The distance between the two LOAD segments is interesting:
    <blockquote>
      <para>
	<literal>VirtAddr</literal>[2] -
	<literal>VirtAddr</literal>[1] -
	<literal>FileSiz</literal>[1] =
	&calc.sh.LOAD2.virtaddr.X; - 
	&calc.sh.LOAD1.virtaddr.X; -
	&calc.sh.LOAD1.filesiz.X; =
	&calc.sh.LOAD2.diff.X; =
	&calc.sh.LOAD2.diff.D; bytes
      </para>
    </blockquote>
  </para>
  <simpara>
    Only &calc.sh.LOAD2.diff.align.D; bytes
    (&calc.sh.LOAD2.diff.align.X;) would be needed to align the first
    LOAD segment up to the alignment of &calc.sh.LOAD1.align.X;.
    For some reason at least one complete page lies between code segment
    and data segment. This would be easy target for a tiny virus.
    So lets check out whether this is a unique phenomenon.
  </simpara>
  <simpara>
    The following <application>Perl</application> script reads
    a list of file names from <literal>stdin</literal>,
    one file name per line.
    <command>readelf <option>-l</option></command>
    is called for every file, and the output is parsed for lines
    starting with the word <literal>LOAD</literal>.
    The end of the segment is calculated and stored for the next line.
    If the distance from the start of a <literal>LOAD</literal>
    segment to the end of the previous one is less than
    <literal>&calc.sh.LOAD1.align.X;</literal>, a message is written.
  </simpara>

  <formalpara>
    <title>Source: src/scanner/dist.pl</title>    <para>
      <programlisting><inlinemediaobject><imageobject><imagedata
        format="linespecific"
	fileref="../src/scanner/dist.pl"
      ></imageobject></inlinemediaobject></programlisting>
    </para>
  </formalpara>

  <simpara>
    You will now experience a time warp. I introduced above script
    as a means to verify the existence of an exploitable peculiarity.
    But this also makes it a tool to check whether the peculiarity
    is already exploited. In other words, it is a scanner.
    For viruses we yet have to develop.
  </simpara>
  <simpara>
    Of course the naive implementation through parsing the output of
    <citerefentry>
      <refentrytitle>readelf</refentrytitle>
      <manvolnum>1</manvolnum>
    </citerefentry> significantly limits performance.
    But use of
    <citerefentry>
      <refentrytitle>file</refentrytitle>
      <manvolnum>1</manvolnum>
    </citerefentry> as a fast file-type filter will lower noise
    (<quote>has 0 LOAD segments</quote>) and duration
    to acceptable regions.
  </simpara>
  <simpara>
    The first test is with typical places like <filename>/bin</filename>.
    Only the last line of output is shown.
  </simpara>

  <anchor id="command.big.sh">
  <formalpara>
    <title>Command: src/scanner/big.sh</title>    <para>
      <programlisting><inlinemediaobject><imageobject><imagedata
        format="linespecific"
	fileref="../src/scanner/big.sh"
      ></imageobject></inlinemediaobject></programlisting>
    </para>
  </formalpara>
  <formalpara>
    <title>Output: out/i386/scanner/dist_big</title>    <para>
      <programlisting><inlinemediaobject><imageobject><imagedata
        format="linespecific"
	fileref="../out/i386/scanner/dist_big"
      ></imageobject></inlinemediaobject></programlisting>
    </para>
  </formalpara>

  <simpara>
    Strange result. On my original installation of RedHat 7.2 all
    files could be infected through this method. Since the second
    quarter of 2002 some (but not all) executables of updated
    packages are immune. On a similar installation of RedHat 7.3
    this scanner detects a few hundred files. Either someone is
    actively closing a gap. Or I caught an infection &hellip;
  </simpara>
  <simpara>
    Anyway, there are still enough interesting files left. So on to
    all infected executables created from the sources of this document.
  </simpara>

  <anchor id="command.small.sh">
  <formalpara>
    <title>Command: src/scanner/small.sh</title>    <para>
      <programlisting><inlinemediaobject><imageobject><imagedata
        format="linespecific"
	fileref="../src/scanner/small.sh"
      ></imageobject></inlinemediaobject></programlisting>
    </para>
  </formalpara>

  <simpara>
    Again only the last line of output is shown.
    It's enough to see that all infected files are detected.
  </simpara>
  <formalpara>
    <title>Output: out/i386/scanner/dist_small</title>    <para>
      <programlisting><inlinemediaobject><imageobject><imagedata
        format="linespecific"
	fileref="../out/i386/scanner/dist_small"
      ></imageobject></inlinemediaobject></programlisting>
    </para>
  </formalpara>

</sect2>
<sect2 id="the.plan" xreflabel="The plan">
  <title>The plan</title>

  <simpara>
    You may have heard that Linux is a difficult target for
    <ulink url="http://www.malware.org/malware.htm">malware</ulink>
    because there are so many different distributions.
    Well, they all use basically the same compiler,
    producing the same idiosyncrasies.
    This allows us to cheat in big style.
  </simpara>

  <procedure>
    <step>
      <simpara>
        Insert our code between code segment and data segment.
      </simpara>
    </step>
    <step>
      <simpara>
	Modify inserted code to jump to original entry point afterwards.
      </simpara>
    </step>
    <step>
      <simpara>
	Change entry point to start of our code.
      </simpara>
    </step>
    <step>
      <simpara>Modify program header</simpara>
      <substeps>
	<step>
	  <simpara>
	    Include increased amount of code in entry of code segment.
	  </simpara>
	</step>
	<step>
	  <simpara>
            Move all following entries down the file.
	  </simpara>
	</step>
      </substeps>
    </step>
    <step>
      <simpara>Modify section header</simpara>
      <substeps>
	<step>
	  <simpara>
	    Include trailing code in last section of code segment
	    (should be <literal>.rodata</literal>).
	  </simpara>
	</step>
	<step>
	  <simpara>
	    Move all following sections down the file.
	  </simpara>
	</step>
      </substeps>
    </step>
  </procedure>

  <para>
    This setup has two big problems, however.
    <itemizedlist>
      <listitem>
        <simpara>
	  Code size is limited to &calc.sh.LOAD1.align.X; bytes.
	  Manageable with assembly. Tough luck for C.
        </simpara>
      </listitem>
      <listitem>
        <simpara>
	  Infected executables will be detected by
	  <link linkend="turn.the.pages">above
	      <application>Perl</application> script
	  </link>.
	  But you know that already.
        </simpara>
      </listitem>
    </itemizedlist>
  </para>
</sect2>

<sect2 id="paranoid.android" xreflabel="Paranoid android">
  <title>Paranoid android</title>

  <simpara>
    Since all executables in <filename>/bin</filename> and
    <filename>/usr/bin</filename> follow the same layout,
    a heuristic scanner can easily spot deviations.
    A <quote>perfect infection</quote>, resulting in a executable
    indistinguishable from the real thing, is far from sight.
    But then there are bigger issues an innocent virus
    seeking a warm nest in the wild would face.
  </simpara>
  <simpara>
    For example RPM-based distributions maintain a checksum database.
    Verifying a single file, a complete package, or even all installed
    packages takes just one command.
  </simpara>
  <simpara>
    If you know what you are looking for:
  </simpara>
  <screen>rpm --verify -f /bin/sh</screen>
  <simpara>
    For dedicated people with enough time to read the output:
  </simpara>
  <screen>/bin/nice -n 19 rpm --verify --all</screen>
  <simpara>
    A possible counter attack is to patch the database after infection.
    This is distribution dependent and requires root permissions.
    And it won't help against people who have the checksums offline.
    That type of precaution is commonly called
    <quote>Intrusion Detection System</quote>.
    There is a <ulink url="&http.sans.org.ids;">FAQ</ulink>
    hosted by <ulink url="&http.sans.org;">SANS Institute</ulink>.
    And a brief introduction to products is 
    <ulink url="http://www.networkintrusion.co.uk/ids.htm"
      >Talisker's Intrusion Detection System List</ulink>.
    <ulink url="http://www.tripwire.org/">tripwire</ulink> has
    achieved a big name, but there is other free software:
    <ulink url="http://www.snort.org/">snort</ulink>,
    <ulink url="http://www.cs.tut.fi/~rammer/aide.html">aide</ulink>,
    and <ulink url="http://lids.planetmirror.com/">lids</ulink>.
  </simpara>
  <simpara>
    Another possibility is to hide the original (uninfected) executable
    on the file system, and patch the kernel via an inserted module to
    fake calculation of the checksum.
    See <ulink url="&http.samhna;library/lkm.html"
      >Loadable Kernel Module (LKM) Rootkits</ulink>
    at <ulink url="&http.samhna;">&http.samhna;</ulink>.
    And if the kernel is compiled without module-support,
    there is still direct access to <filename>/dev/kmem</filename>
    to install a kernel-patch&hellip;
  </simpara>
  <simpara>On this road lies madness.</simpara>
      
</sect2>
