My thoughts have always been to make more than one valid test in the program. So create a Copy Protection object that contains about 50 different copy protection algorithms (each different). Then in 50 different places call a different CP function.

Yes it can be broken like anything else, but by making 50 or 500 different tests the hacker is going to have to do a LOT of extra effort.