8

I am trying to understand classical buffer overflow exploits where an input buffer overwrites the stack, the function return address that is saved on the stack and upper memory regions (where you usually place the shell code). There are many examples of this on the internet and I think I have understood this pretty well:

  1. You put more data in some input buffer that the developer has made fixed size

  2. Your input overwrites the function arguments and the return address to the calling function on the stack

  3. That address is loaded into EIP when the OS tries to return from the function the overflow happened in and that is what allows you to get data you control into the EIP register (when not reading carefully some articles you get the impression you can overwrite CPU registers. Of course, this is not the case, you can only overwrite the stack but the CPU will load addresses from the stack into its registers)
  4. If the exploit is well designed the value loaded into EIP will make the program jump to the beginning of the shell code (see point 5)
  5. The next thing I think I have understood well is the "JMP ESP" mechanism. When replicating the crash in your lab environment you look for a place in memory that contains the "JMP ESP" instruction and you overwrite the EIP (now my wording is not precise, I know...) with that address. That address needs to be identical no matter how often you run this, at what time, which thread is executing your stuff etc., at least for the same OS version and the address must not contain any forbidden bytes. The code will jump to that address (at the same time the stack is reduced by 4 bytes) so "jmp esp" will jump to the next address in my overflow buffer after the place where I had put the value to overwrite EIP with and that is usually the place where the shellcode goes, maybe prepended with NOPs.

Now comes the question.

All articles I've read so far are looking for the address of the "JMP ESP" instructions in a DLL (which must not be relocatable, not compiled with ASLR, etc.). Why not looking in exe itself for a "jmp esp"? Why does it need to be in a DLL?

I have run the "!mona modules" command in Immunity Debugger and the only module displayed that satisfies all these conditions is the exe itself. When I look in popular exploit databases the address is always in loaded DLLs.

I cannot see any obvious reason for this. The exe can also be located at the same address in memory the same way a DLL can. What is the difference?

kaidentity
  • 609
  • 4
  • 10
  • 26
  • 3
    Just think it through a bit. What kind of attack is most likely to succeed? A single EXE of the exact version you hope for or a DLL that is used in *many* processes, has been around for a while and not easily changed by the EXE owner? – Hans Passant Dec 19 '15 at 10:09
  • Ok, so basically what you are saying is that using an address in a DLL is more likely to succeed in several versions of the vulnerable program whereas if I use an address in the EXE this is only reliable for that specific instance of the program and not other versions? But there is no technical reason why I cannot use an address in the same EXE? – kaidentity Dec 19 '15 at 15:57
  • I am looking again at my example and I think the answer is a lot easier than I originally thought. The exe is loaded at base address 0x004.... and goes up to 0x009.... This simply means that the every address will contain a 0x00 which is probably a show stopper for each C like program... – kaidentity Dec 19 '15 at 17:04

3 Answers3

4

Found another resource on this: As I wrote in a comment before, the addresses of the exe usually contain a zero:

http://resources.infosecinstitute.com/in-depth-seh-exploit-writing-tutorial-using-ollydbg/#commands

A module you can consider using is the main executable itself, which is quite often not subject to any compiler based exploit protections, especially when the application has been written by a third party developer and not Microsoft. Using the main executable has one major flaw however, in that it almost always starts with a zero byte. This is a problem because the zero byte is a string terminator in C/C++, and using zero bytes as part of strings used to overflow a buffer will often result in the string being terminated at that point, potentially preventing the buffer from being appropriately overflowed and breaking the exploit.

kaidentity
  • 609
  • 4
  • 10
  • 26
  • Corlan is also a good reference. It states: "we cannot just overwrite EIP with a direct memory address such as 000ff730. It’s not a good idea because it would not be reliable, and it’s not a good idea because it contains a null byte." As stated in the answer, Null bytes seems to be the issue. – Goaler444 Jul 11 '16 at 09:08
2

In position independent code jump addresses are relative to the program-counter, while in non-relocatable code they are absolute. DLLs in Windows do not generally use position independent code. Exploits that rely on knowing the offset of the executable code in the binary require non-relocatable code.

Clifford
  • 88,407
  • 13
  • 85
  • 165
  • The down-voters would do well to explain what the problem with this answer is. Posted in good faith, a punitive down-vote achieves nothing for the SO community unless we have some idea why it is not a helpful answer. – Clifford Dec 20 '15 at 09:40
  • I didn't downvote your answer but I cannot see any help in it either because it doesn't answer my question at all. My question was about why can't I look in the exe file itself for a jmp esp. – kaidentity Dec 20 '15 at 10:09
  • 1
    @kaidentity: The sentence in your text with a question mark (i.e the question) is *"Why does it need to be in a DLL?"*. Exe's are position-independent, and the jump address is relative, not absolute. – Clifford Dec 20 '15 at 13:19
0

short answer: the address DOES NOT need to be in a DLL.

long answer:

ANY mapped unprotected executable memory in your process will be executed if the Instruction register is set to its address.

MAPPED: means the memory is mapped to your process by the operating system, some addresses may not be mapped and any and all access will cause operating system memory fault signals to be raised.

EXECUTABLE: mapped memory often has permissions set to it, sometimes it is enough for the memory to be readable yet with newer processors with NX-bits it may be required to be mapped executable

UNPROTECTED: means that the memory is not mapped as a guard page. memory pages that are protected by guard pages will raise processor interrupt. the handling of these depends on your operating system and may be used to implement non-executable pages on processors that do not implement NX-bits.

if the memory in your executable file fulfils these demands it CAN be used for your exploit. whether you can FIND this address during runtime is another question and can be very difficult for real world exploits. sticking to non relocatable DLLs and EXEs is a good idea for beginners.

as for your comment:

I am looking again at my example and I think the answer is a lot easier than I originally thought. The exe is loaded at base address 0x004.... and goes up to 0x009.... This simply means that the every address will contain a 0x00 which is probably a show stopper for each C like program...

trying to overrun previous addresses with new addresses that contain '\0' characters may cause problems for exploits that use an overrun in string based functions (eg. strcpy or gets) to overflow the buffer because those stop on '\0' characters.

if you can overflow your buffer with logic that is not limited by '\0' characters (eg memcpy) you may use those addresses as well.

user3076936
  • 169
  • 13