Using Lazarus Registration to implement "Try Before You Buy" style shareware
A lot of software, including Lazarus Registration, has a "try before you buy" feature. Implementing this can be a pain in the tail though. You must either build two versions of your software, or devise some way to check the registration code in your program. This is where the registration component steps in.
The first step is to not use the registration component in your installer. Instead, you're going to put an interface in your program to collect the registration information and write it out to a file. In my example code below that file is called registration.conf and uses the same format as the registration.conf file included with the registration component. Change the names to suit your own needs.
Next, you'll need to include the code below into your application. I provided examples in C, because that's what I'm most comfortable with and that's the easiest option when using the registration component. You can adapt this code to your own development environment as necessary.
/* Picks up definition of REGISTRATION_MD5 */
#include "regsanity.h"
#include "config.h"
int app_is_registered()
{
const char *md5 = NULL;
config_t conf = NULL;
FILE *cfile = NULL;
char *serial = NULL;
char *regkey = NULL;
md5 = getmd5("regmyapp.dll");
if (strcmp(md5, REGISTRATION_MD5))
return 0; /* Not the DLL we shipped, don't trust it */
cfile = fopen("registration.conf", "r");
if (!cfile)
return 0; /* No config file, not registered */
conf = config_read(cfile);
fclose(cfile);
serial = config_get_string(conf, "reg-serial");
if (!serial)
return 0; /* No registration information present */
regkey = config_get_string(conf, "reg-key");
if (!regkey)
return 0; /* No registration information present */
/* Actually confirm if the registration code is valid */
return confirm_registered(serial, regkey);
}
const char* getmd5(const char* filename) {
FILE* in;
char* buffer;
md5_state_t pms;
md5_byte_t digest[16];
static char key[33];
int i;
struct stat sb;
char *pos;
if (stat(filename, &sb)) {
perror(filename);
return NULL;
}
buffer = (char*)calloc(1, sb.st_size + 1);
memset(key, 0, 33);
in = fopen(filename, "rb");
fread((void*)buffer, 1, sb.st_size, in);
fclose(in);
md5_init(&pms);
md5_append(&pms, (const md5_byte_t *)buffer, sb.st_size);
md5_finish(&pms, digest);
pos = key;
for(i=0; i < 16; ++i) {
sprintf(pos, "%2.2x", digest[i]);
pos += 2;
}
return key;
}
You should call app_is_registered() when your program first starts, to disable features or turn on the bits that mark your app as a demo. You might also want to run this check in multiple places, as Patrick McKenzie suggests in his excellent article on software registration systems.
Nothing could be simpler. Now you just release your application to the public, let them try it out, and when they register they get the full deal.

![View your cart items []](/sites/all/modules/ecommerce/cart/images/cart_empty.png)

Any proposed solutions?
What you say is true. A determined hacker will get in, and there's precious little that can be done about it. If the computer can read the file (which it must do to run the file) then a hacker with sufficient knowledge can get into the file. Likewise, if the hacker can write to the file (which they will be able to do) they'll be able to modify it to suit their needs.
There's no magic bullet to defeat the determined hacker. But there are obstacles that can be put in their way to make it harder. Patrick McKenzie's article is also worth a read. He has some good ideas about raising the bar for the hackers who can get at your code.
As a start, try stripping the executable before shipping. By removing debugging information the bar is just slightly higher.
--
Clay Dowling
President
Lazarus Internet Development
Not all that good
Any hacker who isn't a completely incompetent buffoon would patch app_is_registered() to always return true - it won't do any of the checks at all. Even if it's called from a billion locations, it won't change the result. Plenty of utilities will help them find all the code that accesses the "registration.conf" file. Even if you obscure the filename, the filesystem access can be detected and there's nothing you can do about it.
At best, if you inline the code so it's actually performed multiple times (and manage to stop the optimiser from noticing) the hacker will identify the code and then seach the file for all instances that match the pattern or access the particular file.
Or maybe he could patch calls to getmd5() to jump to his new hacked_getmd5() so that when called with argument "regmyapp.dll" it changes the string to "original_regmyapp.dll" and otherwise just calls the original function - you're running with the hacked DLL and doing your checks against the wrong file.
My x86 assembler knowledge is, well, not good - but the damn hackers are just difficult bastards who know stuff like that.