Немного расскажу как делал защиту я. Без всяких дополнительных библиотек. Берём некий кусок программы, длиной x байт (можно использовать указатель на main, или на какой-нибудь текст из программы, например список менюшек). Генерируем случайный байтовый массив той же длины. Генерируем случайный набор простых операций над этими двумя массивами (побитовые операции, арифметические) так чтобы на выходе получился массив той же длины. Последовательность действий записываем. Лицензионный код это первые x байт и сразу за ними x результирующих байт в 16ричном виде. Теперь берём сгенерированный код и раскидываем его кусками по разным частям кода инициализации, нужно только четко представлять последовательность. Так чтобы к моменту загрузки где то просчиталось и куда то сложилось то, что получилось из первой части. В конце сравниваем 1 байт из второй части лицензии с результатом и ругаемся если не совпадает. По остальному коду в случайных местах раскидываем сравнение других байт. Понятно, что и результат неплохо бы не в одном месте хранить. 1 байт в одном модуле, другой в другом. Защита не идеальная, но прекрасно показала себя.