Quote:
Originally Posted by compaq
you can get eip to = 41414141, the reason you can't point it to the shellcode directly is becuse of 0x00.
|
Not quite. The reason that EIP cant be pointed to the shellcode directly is because of SafeSEH preventing the overwritten SEH entry from being used as an exception handler for the program, which is what gives us control of EIP.
When the SEH entry is \x41\x41\x41\x41 it will get passed to the program as an exception handler, and then get placed in EIP, because that address does not sit within a loaded module protected by SafeSEH. Where the SEH entry points to an address in a loaded module protected by SafeSEH, that address does not get passed to the program as an exception handler, so it does not get placed in EIP.
The usual method for controlling EIP with an SEH overwrite is (and this is a simplified explanation):
- A crash occurs in the program. If you are monitoring the program in a debugger at this point the execution will pause and you will need to pass the exception through to the program to be handled. At this point in the 3CDaemon, EIP HAS NOT been overwritten with a value from our buffer, but the SEH address on the stack HAS been overwritten with our buffer.
- Once the exception has been handed to the program, it will start to try and handle the exception with SEH, which is usually done by pointing EIP to the SEH address BUT some checks are performed before this is done depending on the OS version and patch level
- On XP SP2 and above, before the EIP register is directed to SEH SafeSEh comes into effect. If the SEH entry points to an address within a loaded module, the SEH handler first checks to see if that module was compiled with the SafeSEH ON switch. If so, it won't redirect EIP to that module, unless the particular address being redirected to is one of the registered handlers for that module. You wont be able to redirect to modules with No SEH at all.
So how do you get around this?
- You redirect execution to a module that is compiled with SafeSEH OFF. Usually only third party modules have this switch, and there are none for 3CDaemon.
- You redirect to an address within the main executable itself. This doesn't work in this case because the \x00 in the address prevents the buffer from overflowing
- You load an instruction (pop, pop, ret or jump/call ptr esp/ebx) from a predictable spot in memory outside of a loaded module, so the SafeSEH module checks don't stop you. The only address that I could find that fits the bill also had a \x00, which stops the buffer from overflowing.
- You load an instruction from a predictable spot on the heap. I haven't yet found a way to write to the heap for this application.
- Use a registered handler from a SafeSEH module to get code execution. I haven't checked all registered handlers yet (there are a lot of them and there's no automated means to quickly check their contents), but this method doesn't usually work.
So, the upshot of this is, while EIP CAN be overwritten with \x41\x41\x41\x41, it can't be overwritten with any address that's actually useful in order to give us code execution. This is because the only such addresses are within loaded modules and SafeSEH prevents us from getting these addresses from the SEH entry into EIP. So at this point, we haven't actually gotten control of the CPU, so we cant run any form of shellcode as yet.
As you mentioned, I think that ECX does get overwritten with the same value as EIP when \x41\x41\x41\x41 is passed to the program as an exception handler by SEH, but I don't see how a useful value can be placed in ECX without first placing it in EIP. If the SEH address points to a PSH ECX, RET (or similar) instruction, this would just create a loop.