[Solved] C’s strange pointer arithmetics [closed]


As pointed out by others, this statement suffers from undefined behavior:

*(&x+5) += 7;

Memory address &x+5 is outside the bounds of variable x. Writing to that address is a very bad idea.

OP’s code sample exploits certain C compiler implementation details.
Probably educational; it can be used to demonstrate how hackers can exploit missing bounds checks to change the designed behavior of a program.

It is interesting enough to investigate the actual behavior of this program.
I will assume the program has been compiled by GCC with default settings on a 64-bit Linux distro on Intel x64 processor architecture (i.e. little endian).
Pointers are 64 bits (8 bytes), int is 32 bits (4 bytes).

Variable x is located on the stack. During execution of k(), the stack looks like this:

+--------+----------------------------------------------------+  TOP OF STACK
| rsp+0  | unused; 16-byte alignment filler                   | <--- rsp
+--------+----------------------------------------------------+
| rsp+4  | x                                                  | <--- &x
+--------+----------------------------------------------------+
| rsp+8  | reserved; least significant 32 bits of stack guard |
+--------+----------------------------------------------------+
| rsp+12 | reserved; most significant 32 bits of stack guard  |
+--------+----------------------------------------------------+
| rsp+16 | least significant 32 bits of saved base pointer    | <--- rbp
+--------+----------------------------------------------------+
| rsp+20 | most significant 32 bits of saved base pointer     |
+--------+----------------------------------------------------+
| rsp+24 | least significant 32 bits of return address of k() | <--- &x+5
+--------+----------------------------------------------------+
| rsp+28 | most significant 32 bits of return address of k()  |
+--------+----------------------------------------------------+
| rsp+32 | start of stack frame of main()                     |
+--------+----------------------------------------------------+

&x+5 is a memory address that is 20 bytes away from &x (because sizeof(int) is 4).
That happens to be the location of the return address of k().
*(&x+5) += 7 will increase the return address by 7.
That will have its effect when returning from k() to main().
Here is objdump output of main():

void main(void)
{
  45:   55                      push   rbp
  46:   48 89 e5                mov    rbp,rsp
  49:   48 83 ec 10             sub    rsp,0x10
        int y = 1;
  4d:   c7 45 fc 01 00 00 00    mov    DWORD PTR [rbp-0x4],0x1
        y = 13;
  54:   c7 45 fc 0d 00 00 00    mov    DWORD PTR [rbp-0x4],0xd
        k();
  5b:   e8 00 00 00 00          call   60 <main+0x1b>
        y = 2;
  60:   c7 45 fc 02 00 00 00    mov    DWORD PTR [rbp-0x4],0x2
        printf("y = %d\n", y);
  67:   8b 45 fc                mov    eax,DWORD PTR [rbp-0x4]
  6a:   89 c6                   mov    esi,eax
  6c:   48 8d 3d 00 00 00 00    lea    rdi,[rip+0x0]        # 73 <main+0x2e>
  73:   b8 00 00 00 00          mov    eax,0x0
  78:   e8 00 00 00 00          call   7d <main+0x38>
}
  7d:   90                      nop
  7e:   c9                      leave
  7f:   c3                      ret

The program is supposed to return from k() at offset 60 (the start of y = 2), but instead, it will return at offset 67 (the start of printf("y = %d\n", y)).

In other words, after returning from k(), the program will skip y = 2 and continue from printf("y = %d\n", y), printing y = 1.

solved C’s strange pointer arithmetics [closed]