Professional Documents
Culture Documents
When Every Byte Counts Writing Minimal Length Shellcodes
When Every Byte Counts Writing Minimal Length Shellcodes
Abstract—Against vulnerable binary applications both ethical Moreover, the basic egg-hunting technique has several
and malicious hackers frequently apply an exploitation technique extensions. If the attacker can control more than one buffer,
called egg-hunting. Egg-hunters are small shellcodes whose goal is which are all small, an omelette egg-hunter [9] can be used
to search for a usually longer and less restricted egg that executes to collect, assemble and run the snippets. The integrity of the
the next phase of the attack. Here, this method is investigated egg-code can be checked by the so-called egg-sandwich [10]
from several new aspects. First we try to establish the length of
the minimal egg-hunter code under various assumptions. Next,
method. After being found the egg-code is usually required
we study how this technique can be combined with a modern to be made executable, e.g. via a VirtualProtect call [11].
exploitation technique of return oriented programming (ROP). Lastly, some egg-hunters are tailored to run in the WoW64
Lastly, a brief evaluation is given of both the advantages and environment [12].
drawbacks of egg-hunting.
Due to space limitations the egg-hunting method will not
be introduced in detail. The readers not familiar with this
I. I NTRODUCTION technique are asked to read the paper by Matt Millner (Skape)
Nowadays attacks against binary programs are often rather [2], where the basics are explained clearly and concisely.
complex. Attackers apply several hacking techniques and Here, the aim of this paper is to analyse several specific
exploit various vulnerabilities. E. g., to win the Chromium questions about egg-hunting like the minimal size of the egg-
Security Reward in 2012 Sergey Glazunov chained together hunting shellcodes and the memory page protection bypassing
14 bugs [1]. This also implies that attacks usually occur in possibilities.
several stages, which means that the progress is gradual. Each
of these steps has a specific goal in the attack-chain like leaking II. M INIMAL L ENGTH E GG - HUNTER S HELLCODES
a certain pointer, writing in an arbitrary memory address and
finally executing the attacker-supplied payload code. Evidently, the length of egg-hunters depends on their
functionality and the circumstances of the exploitation.
In a restricted environment the exploit development raises
the question of what the length of the shortest “meaningful” Functionality first of all means how reliable finding the egg
shellcode is. Naturally, it could be a single byte, when the is. In general 8 bytes or 2 x 4 bytes is enough for the unique
shellcode is just a RET instruction used, for instance, to turn identification of the egg-tag, but in certain cases, especially
off an access control check or an exception handler code. Next, when the attacker knows in advance that the egg-tag will be
the attacker could make a short or long jump that takes up 2 or located not far from the start address of the search, fewer
5 bytes, respectively. E.g., jmp short $ causes an infinite (1 or 2) bytes may be sufficient. Naturally, performing either
loop, hence it can be used in denial of service (DoS) attacks. a syscall-based or SEH-based segfault check [2] significantly
Someone can also apply a few bytes shellcode to read or set increases the code size, hence here and below just blind egg-
an address in the memory, and the next shortest shellcodes hunters as candidates for minimal length shellcodes will be
are probably the so-called egg-hunters, the main topic of this investigated.
article.
The other important factor is the circumstances, in partic-
During egg-hunting an attacker uses a small shellcode, ular the environment in which the egg-hunter runs, e.g., the
called an egg-hunter in order to find and execute a usually value of the registers, the content and alignment of the stack,
longer and less restricted payload, which will be called an heap and code segments. If, for example, a register always
egg-code. The egg-code can be anywhere in the memory. contains a fixed value at the point of exploitation, then one
can move that value into the eax register by mov eax,reg
This technique is not new. The main general reference [2] instead of move eax, 0xAABBCCDD, which requires only
was written by Matt Miller (Skape), which provides a very 2 bytes instead of 5. Next, some examples for small blind
clear exposition of the subject. Egg-hunting usually appears in egg-hunters are presented. These examples were created by
the advanced part of shellcode development tutorials, e.g. [3]– incorporating some ideas of other researchers [2], [6].
[5], to name a few. Egg-hunters are also used in malware [6]
especially in rtf [7] and pdf [8] documents, where the payload The first snippet of code called Hunter 1 is a standard blind
can easily be embedded into the document itself. egg-hunter that starts the search from the top of the stack using
Hunter 1 Blind egg-hunter – 4-byte egg-tag (12 bytes) are two common methods available to avoid this. First, an
0: 89 e7 mov edi, esp operation can be used, (e.g., inc or dec) on the eax register
2: b8 45 47 47 21 mov eax, 0x21474745; ”EGG!” before using its value as an egg-tag, so in the code one could
7: af scasd write a number one more or one less than the egg-tag. Second,
8: 75 fd jne start+0x7 it is standard practice to look for two consecutive appearances
10: ff e7 jmp edi of the egg-tag. This can be done by Hunter 3. Again, the
egg-tag is “recycled” as code. The search is done in bytes
6–10, but here repe (repeat while equal) is used instead of
a 4-byte egg-tag that may be arbitrary. It seems that in this case repne (repeat while not equal) and one must set ecx to the
the SCASD (SCan A String Double word) instruction is the value of 2 before the cycle, since the code is looking for a
easiest and most succinct way of performing the search. This double appearance of the egg-tag. This is done in bytes 6–7,
also has the advantage of automatically increasing the address but since these two bytes do not run on the first cycle, another
in edi, which implies that jmp edi can be used to start the instruction, namely inc ecx (in byte 4) is needed to ensure
egg-code, hence the egg-tag does not need to be executable. that ZF=0 in order to take the jump in bytes 10–11.
Here and thereafter the direction flag DF is always assumed
To reduce the code length even further, if the attacker can
to be 0, which means a forward search instead of a backward
safely assume that the upper two bytes of ecx are zeros, then
one. Also, the length of this code is just 12 bytes.
the xor ecx, ecx (bytes 2-3) instruction can be deleted,
leading to an additional 2-byte decrease in the code length.
Hunter 2 Blind egg-hunter – 4-byte fixed egg-tag (11 bytes)
0: 89 e7 mov edi, esp
2: 01 f9 add ecx, edi; also resets ZF=0 Hunter 4 Blind egg-hunter – 1-byte egg-tag (9 bytes)
4: b8 f2 af ff e7 mov eax, 0xe7ffaff2 0: 89 e7 mov edi, esp
5: f2 af repne scasd 2: b0 63 mov al, 0x63; arbitrary egg-tag
7: ff e7 jmp edi 4: 49 dec ecx ; also resets ZF=0
9: eb fa jmp start+0x5 5: f2 ae repne scasb
7: ff e7 jmp edi
The next version called Hunter 2 can save one byte by
fixing the egg-tag. If the egg-tag is chosen to be the “egg- Next, the shortest version is Hunter 4. In order to further
hunter core”, i.e., 0xe7ffaff2 (written in the code with reduce the code length here a single byte for egg-tag is applied
little-endian representation as f2-af-ff-e7, bytes 6–9), using the following assumption, which seems to be acceptable
then these data-bytes may be reused as code if the execution in certain situations:
jumps back (bytes 9–10) into the middle of the operation mov
eax, 0xe7ffaff2 after its execution. In order to use the
repne scasd sequence appropriately the attacker must clear 1) A register reg (like esp) contains an address below the
the zero flag and ensure that the count register ecx contains shellcode and there is no unallocated memory between
a value that is large enough. To be precise, ecx must be these addresses.
greater than the distance between the egg’s location and the 2) At the point of exploitation the value of ecx is either zero
start address of the search. Both of these two goals can be or it is greater than the address of the shellcode minus the
achieved by the instruction add ecx, edi, if it is assumed start address given by reg.
that ecx plus the value of esp (possibly after overflow) is 3) The otherwise arbitrary one-byte egg-tag does not appear
large enough (greater than 4096, say, the default length of a between the start address and the beginning of the shell-
memory page). In the rare case when this does not happen, one code.
could replace the addition by subtraction: (2: 29 f9 sub 4) The direction flag DF is zero.
ecx, edi).
From these four conditions the third one has the least
Hunter 3 Blind egg-hunter – 2x4-byte fixed tag (14 bytes) chance of occurring, but this is compensated by the fact that
0: 89 e7 mov edi, esp the egg-tag can be chosen arbitrarily. Furthermore, in byte 3
2: 31 c9 xor ecx, ecx one could change the length of the egg-tag to 2 or 4 bytes, and
4: 41 inc ecx; just to set ZF=0 use the scasw or scasd instruction in byte 6 accordingly.
5: b8 b1 02 f3 af mov eax, 0xaff302b1; EGG! This would increase the length of the code to 11 or 13 bytes,
6: b1 02 mov cl, 0x02; ecx=2 since ch=0 respectively.
8: f3 af repe scasd
In this section some variations of blind egg-hunters of the
; compare [edx] with eax twice
minimal length were realised. It is quite possible that these
10: 75 fa jne start+0x6
“length records” can be improved by using further tricks or
; ZF=0, so jump is taken first time
considering other assumptions in a concrete situation. The
12: ff e7 jmp edi
aim here was just to demonstrate that egg-hunters, especially
the blind ones, can be really short. Therefore one should not
One drawback of the above two versions is that they search underestimate the capability of an attacker that acquired code
for only a single appearance of the egg-tag, thus they might execution even if a severe restriction is applied on the size of
find it in their own code before finding it in the egg. There the code that he can use.
– 270 –
Authorized licensed use limited to: London Metropolitan University. Downloaded on March 20,2024 at 13:45:25 UTC from IEEE Xplore. Restrictions apply.
SISY 2015 • IEEE 13th International Symposium on Intelligent Systems and Informatics • September 17–19, 2015, Subotica, Serbia
Using ROP with egg-hunting the attacker has several 0x28 + nops length Classic egg-hunting
options:
A. Applying ROP by turning off the memory page protection be moved to a register. Multiplying it by a certain value, the
(it is possible with several APIs), then executing the egg- stack distance can be set for the two different cases of the
hunting code on the originally protected region; condition. The following ROP program shows how it can be
B. Applying ROP as egg-hunting by condition evaluation and performed in theory (assuming that all the necessary gadgets
cycles; are available). Theoretically the minimum size of the egg-
C. Applying ROP by copying the egg-hunting code to an hunting ROP program is 56 bytes in 32-bit systems; however
executable memory region and launching it. it looks only for a simple 4-byte egg-tag instead of two 4-byte
values. Table II shows the gadgets needed to carry out the task.
A. Egg-hunting after altering memory page protection by ROP
ROP egg-hunting with memory page protection alteration TABLE II. S TACK LAYOUT FOR DIRECT CONDITION EVALUATION .
combines two techniques, namely the memory page protection
Addr. Value Explanation
modification and the classic egg-hunting. First, the memory
page protection has to be turned off for the codepage where 0x0 Address of pop ecx gadget Set the value of the egg-tag in ecx
the egg-hunting shellcode is placed (using e.g. VirtualProtect 0x4 The value of the egg-tag
or VirtualCreate). It is also possible to create a new executable 0x8 Address of pop eax gadget This is the difference on the stack in
bytes between the two branches of
memory region and copy the egg-hunting shellcode there (e.g. the conditions
using HeapCreate + MemCpy). 0xc 0xffffffe0 -32
For the simplest case, the stack layout should look like that 0x10 Address of pop ebx gadget The egg hunting starts using this
address
given in Table I. In this case the address of the VirtualProtect
0x14 Start address - 1
method is placed on the stack with its parameters. The first
0x18 Address of inc ebx gadget The beginning of the cycle, the cycle
parameter is the address of the memory region where the variable is ebx
page protection has to be changed. Now it is treated as 0x1c Address of xor edi, edi gadget Sets edi to zero
a deterministic value (esp+0x18+nops length), but for 0x20 Address of mov edx, ecx gadget Move the egg to a temporary vari-
a general solution obtaining the current stack pointer and able
calculating the place where the classic egg-hunting code is 0x24 Address of sub edx, [ebx] gadget Subtract the value at the current in-
placed would be preferable. dex from the egg. If the egg is there
the result is zero
0x28 Address of neg edx gadget Negate the subtraction. If the egg is
B. ROP egg-hunting by direct condition evaluation found the carry flag is 0, otherwise
it is 1.
Using the full ROP approach it is necessary to execute
0x2c Address of adc edi, edi gadget Copy the carry flag to edi
cycles with ROP. The attacking code has to compare the
0x30 Address of mul edi gadget Set the stack difference, if the egg
value at a given address with the egg-tag pattern for each has found it is 0, otherwise it is -32
step of the search. The classical comparison (cmp x,y je 0x34 Address of add esp, edi gadget Set esp according to the condition
address) formula obviously cannot be used, since the gad- 0x38 Address of mov esp, ebx gadget Set esp to the place where the egg
gets are scattered in the virtual memory, so the je address has found
formula is useless. There are several ways available to execute
condition evaluation in ROP [14], but the classic solution is to
subtract the two values that have to be compared and negate In addition, the given solution has another drawback. It
the result. If the two values are the same the carry flag will applies the blind egg-hunting technique, so if a memory
be zero; otherwise it will be 1. Then with an adc (add with address is not readable at the analysed region then the code
carry) instruction on a zero the value of the carry flag will crashes. Considering the Turing-complete behaviour of ROP,
– 271 –
Authorized licensed use limited to: London Metropolitan University. Downloaded on March 20,2024 at 13:45:25 UTC from IEEE Xplore. Restrictions apply.
Z. L. Németh and L. ErdĘdi • When Every Byte Counts – Writing Minimal Length Shellcodes
checking the readability of a memory address before reading Fig. 1. The role of egg-hunting.
it with ROP is possible, but obviously it increases the size of
the egg-hunter.
– 272 –
Authorized licensed use limited to: London Metropolitan University. Downloaded on March 20,2024 at 13:45:25 UTC from IEEE Xplore. Restrictions apply.
SISY 2015 • IEEE 13th International Symposium on Intelligent Systems and Informatics • September 17–19, 2015, Subotica, Serbia
– 273 –
Authorized licensed use limited to: London Metropolitan University. Downloaded on March 20,2024 at 13:45:25 UTC from IEEE Xplore. Restrictions apply.
Z. L. Németh and L. ErdĘdi • When Every Byte Counts – Writing Minimal Length Shellcodes
Summing up, egg-hunters should be viewed as small, [10] M. Czumak. (2015, Febr.) EggSandwich – An Egghunter with In-
staged shellcodes, whose real strength lies in their small code tegrity, Security Sift Blog.[Online.] Available: http://www.securitysift.
size, which means there is great scope in exploiting a system com/eggsandwich-egghunter-integrity/
and avoiding mitigation in many cases. [11] Corelan Team. (2011, May.) Hack Notes : Ropping eggs for break-
fast. [Online.] Available: https://www.corelan.be/index.php/2011/05/12/
hack-notes-ropping-eggs-for-breakfast/
ACKNOWLEDGMENT [12] Corelan Team. (2011, Nov.) WoW64 Egghunter. [Online.] Available:
https://www.corelan.be/index.php/2011/11/18/wow64-egghunter/
The authors wish to thank David P. Curley for checking
[13] R. Roemer, E. Buchanan, H. Shacham, and S. Savage, “Return-oriented
the paper from a linguistic point of view. programming: Systems, languages, and applications,” ACM Transac-
tions on Information and System Security (TISSEC), vol. 15, no. 1, pp.
R EFERENCES 2, 2012.
[14] H. Shacham, ”The Geometry of Innocent Flesh on the Bone: Return-
[1] K. Buchanan, Ch. Evans, Ch. Reis, T. Sepez (2012 Jun.) A Tale Of into-libc without Function Calls (on the x86),” in CCS 2007, pp. 552–
Two Pwnies (Part 2), Chromium Blog. [Online.] Available: http://blog. 561, ACM Press, 2007.
chromium.org/2012/06/tale-of-two-pwnies-part-2.html
[15] K. Z. Snow, F. Monrose, L. Davi, A. Dmitrienko, C. Liebchen and A.-R.
[2] Matt Miller (Skape) (2004, Sep.) Safely Searching Process Virtual Sadeghi, ”Just-in-time code reuse: On the effectiveness of fine-grained
Address Space. [Online.] Available: http://hick.org/code/skape/papers/ address space layout randomization”, in Security and Privacy (SP), pp.
egghunt-shellcode.pdf 574-588, IEEE, 2013.
[3] Corelan Team. (2010 Jan.) Exploit writing tutorial part 8: Win32 Egg [16] E. Göktaş, E. Athanasopoulos, M. Polychronakis, H. Bos and G.
Hunting. [Online.] Available: https://www.corelan.be/index.php/2010/ Portokalidis, ”Size does matter: Why using gadget-chain length to
01/09/exploit-writing-tutorial-part-8-win32-egg-hunting/ prevent code-reuse attacks is hard,” in Proc. 23rd USENIX conference
[4] M. Czumak. (2015, Febr.) Windows Exploit Development – on Security Symposium, pp. 417-432, USENIX Association, 2014.
Part 5: Locating Shellcode With Egghunting, Security Sift Blog [17] S. Checkoway, L. Davi, A. Dmitrienko, A.-R. Sadeghi, H. Shacham
http://www.securitysift.com/windows-exploit-development-part-5- and M. Winandy, ”Return-oriented programming without returns”, in
locating-shellcode-egghunting/ Proc. ACM conference on Computer and communications security, pp.
[5] A. Thabet. (2012 Febr.) The Art of Win32 Shellcoding. [On- 559-572, ACM, 2010.
line.] Available: http://www.codeproject.com/Articles/325776/The-Art- [18] D. Blazakis, ”Interpreter exploitation,” in Proc. USENIX Workshop on
of-Win-Shellcoding Offensive Technologies (WOOT’10), H. Shacham and C. Miller Eds.,
[6] A. Abbasi, and J. Wetzel, “APTs way: evading Your EBNIDS,” 2010.
Presented at Black Hat Europe 2014, 16-19 Oct 2014, Am- [19] J. Khodaverdi, and F. Amin, “A Robust Behavior Modeling for Detect-
sterdam, [Online.] Available: https://www.blackhat.com/docs/eu-14/ ing Hard-coded Address Contained Shellcodes,” International Journal
materials/eu-14-Abbasi-APTs-Way-Evading-Your-EBNIDS-wp.pdf of Security & Its Applications, vol. 7, no. 5, 2013.
[7] M. Janus. (2013, Aug.) The curious case of a CVE-2012- [20] Ch. Anley. (2002, Jan.) Creating Arbitrary Shellcode In Unicode
0158 exploit. [Online.] Available: https://securelist.com/analysis/37158/ Expanded Strings, The “Venetian” exploit. [Online.] Available: http:
the-curious-case-of-a-cve-2012-0158-exploit/ //www.net-security.org/dl/articles/unicodebo.pdf
[8] D. Liu, H. Wang and A. Stavrou, ”Detecting malicious javascript in [21] A. Sintsov (2010, Mar.) JITed egg-hunter stage-0 shellcode Adjusted
pdf through document instrumentation,” in Dependable Systems and universal for xp/vista/win7. [Online.] Available: https://www.exploit-db.
Networks (DSN), pp. 100-111, IEEE, 2014. com/exploits/13649/
[9] Corelan Team. (2010, Aug.) Exploit notes – win32 eggs-to- [22] Microsoft. Enhanced Mitigation Experience Toolkit (EMET) version
omelet. [Online.] Available: https://www.corelan.be/index.php/2010/08/ 5.2. [Online.] Available: http://www.microsoft.com/emet
22/exploit-notes-win32-eggs-to-omelet/
– 274 –
Authorized licensed use limited to: London Metropolitan University. Downloaded on March 20,2024 at 13:45:25 UTC from IEEE Xplore. Restrictions apply.