It's a good way to do it! The less obvious it is that there is a remaining check hidden, the better. Some games would become impossible to win, but only halfway through or worse. Sometimes with multiple layers hidden in different places that fail at different moment.
I cracked an expensive FPGA simulation program (for which I had the license, but the FlexLM scheme based on the MAC address of the adapter was just too annoying to get working on Linux).
What they would do is have a sort of unit test of their license verification function at runtime. There was a check hidden somewhere that I never found, and if the license verification was changed to always return true, the unit test would fail. The simulator would continue working within a single module, but as soon as you tried simulating a larger project, it would return undefined values between all the modules, rendering the simulation unusable for any real project =)
(I solved the unit test by having the license check return true only for my hardcoded serial number, which is definitely easier than hunting for the different places where a check might be hidden)
I cracked an expensive FPGA simulation program (for which I had the license, but the FlexLM scheme based on the MAC address of the adapter was just too annoying to get working on Linux).
What they would do is have a sort of unit test of their license verification function at runtime. There was a check hidden somewhere that I never found, and if the license verification was changed to always return true, the unit test would fail. The simulator would continue working within a single module, but as soon as you tried simulating a larger project, it would return undefined values between all the modules, rendering the simulation unusable for any real project =)
(I solved the unit test by having the license check return true only for my hardcoded serial number, which is definitely easier than hunting for the different places where a check might be hidden)