2

I was experimenting with buffer overflow in C, and found an interesting quirk:

For any given array size, there seems to be a set number of overflow bytes that can be written to memory before a SIGABRT crash. For example, in the code below the 10 byte array can be overflowed to 26 bytes before crashing at 27. Similarly, an array of 20 chars can be overflowed to 40 chars before it aborts on the 41st.

Can anyone explain why this is? Also, is the SIGABRT the same as (or caused by) a "segmentation fault"?

Mac OS 10.8 - Xcode 4.6, clang and lldb. Thanks!

#include <stdio.h>

int main(int argc, const char * argv[])
{
  char aString[ 10 ];
  char aLetter = 'a';

  printf("The size of one array slot sizeof( aString[0] ) is %zu\n", sizeof(aString[0]));
  printf("The size of one letter     sizeof( aLetter )    is %zu\n", sizeof(aLetter));

  // Overflow the aString array of chars
  // lldb claims aString is initialized with values \0 or NULL at all locations

  // Substitute i<27 and this code will crash regularly
  for (int i=0; i<26; i++) {
    aString[i]= aLetter;
  }

return 0;
}

EDIT - I've stepped through it in disassembly and found this protection just after the for-loop:

0x100000f27:  movq   226(%rip), %rax           ; (void *)0x00007fff793f24b0: __stack_chk_guard
0x100000f2e:  movq   (%rax), %rax
0x100000f31:  movq   -8(%rbp), %rcx
0x100000f35:  cmpq   %rcx, %rax
0x100000f38:  jne    0x100000f49               ; main + 121 at main.c:26
.
.
.
0x100000f49:  callq  0x100000f4e               ; symbol stub for: __stack_chk_fail
djwbrown
  • 1,091
  • 1
  • 11
  • 15
  • I assume it's some sort of buffer overflow protection, I just would like to know what it is I'm bumping up against. Also, this is purely in the interest of self-education (nothing malicious)! – djwbrown Feb 23 '13 at 08:28
  • 2
    Commenting on close votes: question has example code, it is IMO clear what is being asked (why there's memory protection at this amount of bytes, which seems very low to me), and this is relevant to clang on Mac in general. No need to close. – hyde Feb 23 '13 at 08:35
  • To understand 0x90's answer below, I needed to read up on stack alignment at: http://stackoverflow.com/questions/4175281/what-does-it-mean-to-align-the-stack – djwbrown Feb 24 '13 at 08:33

1 Answers1

3

That is due to the alignment of the stack on mac os.

It is not big news, if you have googled it, you would find the answer:

Why does the Mac ABI require 16-byte stack alignment for x86-32?


It is nice to see you can actually write to the stack with no side affect in chunks little than 16 bytes.

If you exploit it several times you can get into a state where all your malicious code can be lay down and you may execute it in jumps on the stack.

Community
  • 1
  • 1
0x90
  • 39,472
  • 36
  • 165
  • 245
  • I want to mark this answer correct, but I'm still not sure why a 16-byte stack alignment would produce the "cutoffs" above which are not multiples of 16. What explains that? – djwbrown Feb 24 '13 at 08:32
  • @djwbrown can you explain what do you mean by cutoffs? – 0x90 Nov 03 '13 at 08:57
  • @djwbrown, assuming a relatively typical stack frame: suppose all function parameters, the return address, and any other stack data (saved registers, etc) end inside another 16-byte chunk; then locals will be aligned to the next 16-byte boundary. Without diving into the ABI or what others have written about it too deeply, I'm unsure whether it means each local is 16-byte aligned or not, but I assume the answer is yes. If locals are ordered in reverse, then you could potentially write to as much as 16 (end of non-local stack data) + 16 (`aLetter`) + 16 (the buffer) = 48 bytes before it pukes – Brian Vandenberg Sep 15 '14 at 18:30