In this regard, shellcode is not much different from any other
code, and like most other code, shellcode tends to make use of the stack for all of its data
storage needs. Unlike other code, however, shellcode often lives in the stack itself, creating
a tricky situation in which shellcode, by virtue of writing data into the stack, may inadvertently
overwrite itself, resulting in corruption of the shellcode. Figure 9-8 shows a generalized
memory layout that exists at the moment that a stack overflow is triggered.
At this point, a corrupted return address has just been popped off of the stack, leaving
the stack pointer, esp, pointing at the first byte in region B. Depending on the nature of
the vulnerability, we may have been able to place shellcode into region A, region B, or
perhaps both. It should be clear that any data that our shellcode pushes onto the stack
will soon begin to overwrite the contents of region A. If this happens to be where our
shellcode is, we may well run into a situation where our shellcode gets overwritten and
ultimately crashes, most likely due to an invalid instruction being fetched from the overwritten
memory area. Potential corruption is not limited to region A. The area that may
Chapter 9: Shellcode Strategies
205
PART III
Figure 9-7
The shellcode
decoding process
be corrupted depends entirely on how the shellcode has been written and the types of
memory references that it makes.
Pages:
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401