Dailydave mailing list archives

A people's guide to search-shellcode


From: dave <dave () immunityinc com>
Date: Thu, 24 Dec 2009 05:10:59 -0500

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

I'm guessing every team out there has their own methodology on how to do
this, but these are the ones I know about.

In general the problem statement is that you want a SMALL (30-90 bytes
or so) shellcode that you can use when space is at a premium.

While some simple callbacks shellcodes (c.f. ordinal shellcodes,
shellcodes with known addresses, etc.) are also in this size range, the
payload for an exploit may require sophisticated techniques that are
unable to be compressed to that level. For example, an exploit targeting
a browser may require the ability to repair structures in the browser
after exploitation to prevent it from crashing under the user, alerting
them to the attack. Likewise, reliability or protocol tunnelling
constraints may requires a large, complex main shellcode. Hence the use
of a "search" shellcode.

Other design goals are speed - searching all of memory can take some
time, and the more time goes by the more likely the process being
searched is to crash or otherwise misbehave. Likewise, failing to
provide an exit for the shellcode reduces size slightly but sometimes
produces error conditions if the shellcode never finds the main payload,
and simply loops forever at 100% CPU. This tends to alert targets that
something is wrong.

In Windows search shellcode you do not have the ability to use system
functions and you can only use system calls that do not change (your
shellcode may be restricted to some useful subset of Windows versions).

The basic strategy originally was to create an SEH handler - this
essentially emulated the code of IsBadReadPtr() to look through all of
memory, but later versions of Windows (i.e. XP SP2->3) required some
trickery to bypass SafeSEH restrictions. Even more modern versions of
Widnows (Vista/2008/7) have effectively disabled this technique. This is
the technique you can read about in excruciating depth in the
Shellcoder's Handbook. (I wrote this, now obsolete, chapter so the code
you see in the book is cut and paste out of CANVAS.)

Unix exploit developers were already publishing shellcodes that did
their searching using system calls to have the kernel validate shellcode
addresses. You can see Matt Miller writing about using NtDisplayString()
for this purpose on Windows back in 2004 [1]. CANVAS's modern Win32
search shellcode (and I assume others'?) uses NtAddAtom()[2] to validate
the readability of an address.

This technique results in smaller and more compatible shellcode than the
SEH technique, but as Alex Sotirov has (on Twitter) complained of, is
adding lots of Atoms to the internal Kernel tables. (The maximum number
of new additional Atoms in the CANVAS shellcode is == the number of
readable pages in the process - possibly some other shellcodes are using
a per-byte or per-dword check? Likewise, NT should be fine with very
large numbers of Atoms. Be interesting to know what the top limit is
there). We've not seen a lot of instability related to this, but
anything is possible in Windows-land.

Other possibilities for search-shellcode are endless - for example,
parsing the heap structures themselves or searching through the freelist
(most of the time the shellcode is on the heap and often you have enough
control to place your shellcode on a specific freelist slot),
constructing big payloads from tiny fragments[3], optimizing for
reliability by doing checksums (many corrupted copies of your shellcode
often exist on the heap), parsing the PE header and calling
IsBadReadPtr(), disabling SafeSEH (without the use of VirtualProtect()
:>) and using the older SEH style code, or a thousand other things, like
so many different seashells on the beach.

- -dave

[1] http://www.hick.org/code/skape/papers/egghunt-shellcode.pdf
[2]
http://undocumented.ntinternals.net/UserMode/Undocumented%20Functions/Atoms/NtAddAtom.html
[3]
http://skypher.com/wiki/index.php/Hacking/Shellcode/Egg_hunt/w32_SEH_omelet_shellcode
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (GNU/Linux)
Comment: Using GnuPG with Fedora - http://enigmail.mozdev.org

iEYEARECAAYFAkszPjMACgkQtehAhL0ghepuwACZAZxBP7G2pMPu0ijj6u57G1y1
axgAmwS+Q1Bf2mdJ/MOS6YyzFBLobALh
=tSRj
-----END PGP SIGNATURE-----
_______________________________________________
Dailydave mailing list
Dailydave () lists immunitysec com
http://lists.immunitysec.com/mailman/listinfo/dailydave


Current thread: