It should be noted that heap overflows are usually less common than stack
overflows because the sizes of heap blocks are almost always dynamically cal-
culated to be large enough to fit the incoming data. Unlike stack buffers,
whose size must be predefined, heap buffers have a dynamic size (that’s the
whole point of a heap). Because of this, programmers rarely hard-code the size
of a heap block when they have variably sized incoming data that they wish to
fit into that block. Heap blocks typically become a problem when the pro-
grammer miscalculates the number of bytes needed to hold a particular user-
supplied buffer in memory.
String Filters
Traditionally, a significant portion of overflow attacks have been string-
related. The most common example has been the use of the various runtime
library string-manipulation routines for copying or processing strings in some
way, while letting the routine determine how much data should be written.
This is the common strcpycase demonstrated earlier, where an outsider is
allowed to provide a string that is copied into a fixed-sized internal buffer
through strcpy. Because strcpyonly stops copying when it encounters a
NULLterminator, the caller can supply a string that would be too long for the
target buffer, thus causing an overflow.
What happens if the attacker’s string is internally converted into Unicode (as
most strings are in Win32) before it reaches the vulnerable function? In such
cases the attacker must feed the vulnerable program a sequence of ASCII char-
acters that would become a workable shellcode once converted into Unicode!
This effectively means that between each attacker-provided opcode byte, the
Unicode conversion process will add a zero byte. You may be surprised to learn
that it’s actually possible to write shellcodes that work after they’re converted to
Unicode. The process of developing working shellcodes in this hostile environ-
ment is discussed in [Obscou]. What can I say, being an attacker isn’t easy.
Integer Overflows
Integer overflows (see [Blexim], [Koziol]) are a special type of overflow bug
where incorrect treatment of integers can lead to a numerical overflow which
eventually results in a buffer overflow. The common case in which this hap-
pens is when an application receives the length of some data block from the
outside world. Except for really extreme cases of recklessness, programmers
typically perform some sort of bounds checking on such an integer. Unfortu-
nately, safely checking an integer value is not as trivial as it seems, and there
are numerous pitfalls that could allow bad input values to pass as legal values.
Here is the most trivial example:
256 Chapter 7