1

I don't understand the data type of the code that inserts the 4-byte address into the array. We're doing a buffer overflow attack, and we're inserting a four-byte address into the array from the provided source.

Notice that an error occurs if any of the *(long *) & buf [] is missing. However, I do not understand this code. I would appreciate it if you help me.

*(long *) &test[0] = 0x12345678;

*(long *) &test[4] = 0x12345678;

*(long *) &test[8] = 0x12345678;

I don't know the meaning of *(long *) &test[] here.

Inian
  • 80,270
  • 14
  • 142
  • 161
Seong Han
  • 43
  • 4
  • This is almost certainly a bug and will not work reliably. [What is the strict aliasing rule?](https://stackoverflow.com/questions/98650/what-is-the-strict-aliasing-rule) – Lundin Aug 09 '19 at 10:32

2 Answers2

2

Let's analyze *(long *) &test[0] = 0x12345678; in steps (the postfix operators have higher precedence than the prefix operators):

  • test is either an array of bytes or a pointer to an array of bytes. The code handles both cases the same way.
  • test[0] is an lvalue: the first element of the byte array test (or possibly the byte array pointed to by the pointer test).
  • &test[0] is the address of this byte.
  • (long *)&test[0] is the same address, cast as a pointer to long.
  • *(long *)&test[0] = 0x12345678 writes a long value to this address, overwriting test[0], test[1], test[2] and test[3] (on systems with 8-bit bytes and 32-bit longs).

To summarize: the code fragment writes sizeof(long) bytes to the beginning of the byte array test.

Note however a number of implicit assumptions:

  • the size of long can be different from 4. It can even vary from one OS to another for the same processor: sizeof(long) is 4 bytes on 64-bit Windows but 8 bytes on 64-bit linux systems.
  • the order of bytes when writing a long to memory may differ from one architecture to another: little endian 32-bit CPUs will write the bytes 0x78, 0x56, 0x34 and 0x12 in this order, while big endian CPUs will write the same bytes in the opposite order.
  • there is no guarantee that test[0] is properly aligned for writing a long value to it. Intel CPUs are configured by default to accept misaligned accesses for standard integer sizes, but most CPUs cannot be configured this way and misaligned access has undefined behavior.
  • the compiler may take advantage of the strict aliasing rule to optimize accesses to the test array. Since you are modifying via a different effective type, it may be fooled and not reload values from memory:

    char test[12] = { 0 };
    *(long *)test[0] = 0x12345678;
    if (test[0] == 0) {
        // the compiler could assume that `test[0]` is still `0`.
    }
    
chqrlie
  • 131,814
  • 10
  • 121
  • 189
0
//an example as follows
    int test[5] = {0,1,2,3,4};
    //test[0]-->It'value is 0,it's type is int.
    //&test[0]-->Its value is the address of test[0],what is its type? int*.
    //* &test[0]-->how about it?Its value is 0, its type is int too.
    //*(long*)&test[0] -->Its value is 0,but its type is long.