I had suggested that proposed approach does not follow strict aliasing rule
Correct. ptrMsg = (Message *)buffer means that you cannot access the data of ptrMsg without invoking undefined behavior.
You can prove your point with C17 6.5 §7 (cited here - What is the strict aliasing rule?). An lvalue expression such as ptrMsg->var1 = value does not access the stored value through a type compatible with the effective type of what's stored there, nor through any of the allowed expressions.
You can however go from Message to an array of uint8_t (assuming uint8_t is a character type) without violating strict aliasing.
The larger problem is however the presence of the bit-field in the first place, which is non-standard and non-portable. For example, you cannot know which part of the bit-field that is the MSB and LSB. You cannot know how the bits are aligned in the 64 bit type. Using a 64 bit type for a bit-field is a non-standard extension. It is endianess-dependent. And so on.
Assuming the 24 bits refer to bit 31 to 8 (we can't know by reading your code), then proper code without strict aliasing violations, bit-field madness and non-standard "struct padding killers" would look like this:
typedef union
{
   uint32_t var;
   uint8_t  bytes[4];
} Message;
uint8_t buffer[4];
Message* ptrMsg = (Message*)buffer;
uint32_t var1 = (ptrMsg->var >> 8);
uint8_t  var2 = (ptrMsg->var >> 4) & 0x0F;
uint8_t  var3 = (ptrMsg->var) & 0x0F;
Message being "a union type that includes one of the aforementioned types among its
members". Meaning it contains a type compatible with uint8_t [4].
This code also contains no copying and the shifts will get translated to the relevant bit access in the machine code.