You are indeed missing at least three important things.
Your _strcpy is taking arguments in the opposite order of a normal strcpy. This is extremely counter-intuitive and can lead to mistakes. You should define it as _strcpy(dst, src) instead (the destination is the first parameter).
Secondly, your macro directly modifies the arguments. This is ok in a normal function, but definitely not ok in the case of a macro! For example:
char *a = "hello";
char *b = malloc(6);
_strcpy(a, b);
// Now a and b are both invalid, pointing past the end of the strings.
To solve this, you should use temporary variables, and wrap your statements in a do { ... } while (0) block (see What's the use of do while(0) when we define a macro? for more information on why).
A decent final version of the macro would be:
#define _strcpy(dst, src)                \
        do {                             \
            const char *_src = (src);    \
            char *_dst = (dst);          \
                                         \
            while ((*_dst++ = *_src++))  \
                ;                        \
        } while (0)