0

I've found a few related posts about this on the site but non of them explained my problem. The code is described here: Link

My issue is the following:

The author tries to rewrite the return address of the strcpy() function in the notesearch.c program with one in the buffer so that the shellcode (which I understand is implanted machine code in the memory) will be executed.

For that to work he creates a buffer that looks like: nop nop nop ... | shell code .. | return address

From what I understand after the call to the strcpy() function the buffer is put on the stack and overwrites the return value to notesearch.c's main. He does that so when the strcpy() finishes running and wants to return to the main he'll call the return value from the buffer.

What I don't understand are the following:

  1. It seems to me like the injected return address is always perfectly aligned with the original. How can that be?

  2. It said in the book that the injected return address points to the shellcode in the same buffer. Why would we want to put the shellcode in the same buffer and not in another part of the memory? Couldn't that cause an infinite loop?

  3. Why can't we set the return address to that of the shellcode on the buffer? Or to the variable shellcode for that matter?

  4. Can anyone elaborate on how the return address was calculated and why we need the offset?

Community
  • 1
  • 1
matanc1
  • 6,525
  • 6
  • 37
  • 57

1 Answers1

0

Why would we want to put the shellcode in the same buffer and not in another part of the memory?

Well you are actually free to place the shellcode wherever you want as long as you can execute instructions in that memory region. That being said, this example demonstrate a stack based buffer overflow, in such exploits it's pretty easy to discover the offset of a local variable inside the current stack frame.

Couldn't that cause an infinite loop?

Assuming the shellcode doesn't contains a such infinite loop - no. Yet that might produce bugs since you are modifying the execution flow. This really depends of the shellcode. For instance most shellcode are used to spawn a shell - let's assume the exec function family is used - so once the shell spawns the original executable image will be overridden by the shell.

Why can't we set the return address to that of the shellcode on the buffer?

You can, this only require a more precise calculation. Using the NOP sled you have multiple possible hit that will enable your shellcode execution.

Can anyone elaborate on how the return address was calculated?

The author took the address of the first declared local variable and computed the displacement to the vulnerable buffer. The first drawback here is that the first declared variable (i) might not be the first local variable once compiled. If you want to ensure such constraint a workaround is to use a struct (See: Order of local variable allocation on the stack).

The author probably ran the program multiple times and adjusted the offset until the shellcode gets triggered. Keep in mind that computing the exact address of the buffer is really platform and compiler dependent. You will have to debug your program and inspect how the compiler elaborates stack frame etc.

Why we need the offset?

Because of the stack frame layout a "valid" offset is required to find an address who will hits the NOP sled.

Community
  • 1
  • 1
dna
  • 1,085
  • 7
  • 15