Vulnerability Development mailing list archives

RE: Buffer Overflow Help


From: "Chris Eagle" <cseagle () redshift com>
Date: Sun, 14 Nov 2004 22:24:17 -0800

You need to read the kernel sources to understand what happens when a
process
starts up.  For specific information on the behavior you are witnessing, I
suggest you take a look at the file fs/binfmt_elf.c, specifically the
create_elf_tables function.

The last time I looked at it, these facts were true:

1. This behavior is not enabled in all Linux kernels, but RedHat 9 is one in
which it is enabled.  Anyone that participated in the CTF qualification
round
for the most recent Defcon saw this same behavior on the box setup by
Ghetto.

2. The size of the padding is cyclic based on PID. If you have discovered a
return address that will successfully exploit a process, then that same
return
address should work at least 1/64 of the time because every time the process
is
rerun with a pid that differs from your original pid by a multiple of 64,
the
padding will be the same size and all stack-based buffers should fall in the
same place as they did for your successful exploit. With this in mind, if
you
find a return address that should work but doesn't, rerun your exploit and
the
change in padding will drive your payload towards your return address.

3. The padding grows by 128 bytes each time the PID increments by one.
If the minimum stack jump is 128 bytes, then you can survive a single jump
without changing your return address as long as you can get a NOP sled of at
least 128 bytes. The larger your NOP sled, the more jumps you can survive
until
you become almost 100 percent survivable if you can cram 8192 NOPs into a
stack-based buffer (128 x 64 == 8k)

4. If you know the PID of the parent process, then you know the exact
amount of padding that will be used and you can more accurately compute your
return address. This is particularly useful when performing local exploits
for
which the pid is easily determined.

5. For local exploits, forget about returning into stack-based buffers and
return into an argument string or, better yet, an environment variable.
Argument
and environment strings do not shift in memory when the padding field
changes
size since they lie deeper in the stack than the padding bytes.

RedHat throws a wrench into this as jiffies factors into their equation
along
with PID, so things do not seem to progress quite linearly all of the time.
The
maximum padding size remains restricted to 8k however.

Chris

-----Original Message-----
From: Steve Bonds [mailto:kzzvt3302 () sneakemail com]
Sent: Friday, November 12, 2004 3:05 PM
To: vuln-dev () securityfocus com
Subject: Re: Buffer Overflow Help


On Fri, 12 Nov 2004 09:38:40 -0700 (MST), sin sin-at-nosec.net wrote:
That doesn't really look like randomization to me- its um, not
incredibly
random. I think your environment is changing. It just looks like the
stack frame is being incremented.

I agree, hence my comment that there was a pattern to the changes.  It
increments, reaches an upper limit, then cycles around.

Regardless of the source or quality of the "randomization" the stack
pointer changes during each invocation.  I have no idea why there's
this difference between RH8 and RH9.

Also, since I have no way to predict the next stack location (even
though it's predictable based on the previous one) I can't hit my
shellcode without a large NOP sled.  In the exploit I'm working on,
there's only about 50 bytes of NOP sledding available, after tight
shellcode and I get one chance or the app crashes.  The stack pointer
ranges across about 30k, so my odds of hitting the NOP sled are not
good for a one-shot deal.

On the off chance that perhaps this was really a gcc problem, I
compiled the sample code I posted earlier on statically linked on RH8
and tried it on RH9.  I saw the same stack variations, so it's
probably not gcc or library related.

Anyone know why Red Hat 9 has this strange stack behavior?  How
to disable it?

  -- Steve



Current thread: