///////////////////////////////////////////////////////////////////////////
// 06. A Product Registration Technique                                  //
//     By: Kerry D. Mathews II                                           //
//     Email: mcg@dialisdn.com                                           //

///////////////////////////////////////////////////////////////////////////

There was a time, in my career as a software
developer, when it was necessary to 'burn in'
a registration number into the software.
The registration number had to be uneditable
once entered. And of course, for those few
people who would take a peek at the binary, the
registration number had to be undecipherable.

OK. No problem. I thought. What a foolish hack
I was then.

Well in this article,
I'll show you the techniques used then. It was
originally built for use on DOS executables built
by BC++. It may work on other platforms.
I don't claim any rights or responsibility
to this or any technique.

In later articles, I'll describe approaches from
a more experienced view point.

For this example let's assume the target has only
one source file, and one header, and we're going to
create only one large model DOS executable.



First ...
We're going with the approach of burning a register
number in the main executable itself.

So why not declare a char string like:

     unsigned char reg_info[65];

...and fill it with a somewhat useful string:

sprintf( reg_info, "%s", "This copy of ___.exe v2.0 is unregistered! Please
                                                        register !!   " );

...and this will be our placeholder.
Do notice that the reg_info variable is
completely filled.

If one used a text editor to view the executable,
it would look mostly like garbage. But near the
bottom you can see all the string segments. The
string/data segment that looks like out reg_info
variable is what we'll physically manipulate later.

What you do to verify the end variable will be left
to you. The latest trend is to incorporate IP
software to send the registration info to the
software manufacturers internet address.



Second...
We'll need to create two utility programs. Lets
call them Packager and Register.

Packager is an executable that merely joins two
files but with a nifty twist. Packager opens the
target, in this case it's the Register program.
Also opened is the infile, which is the Main executable.
Here's the snip:

     fseek(infile, 0L, SEEK_END);
     length = ftell(infile);
     fseek(infile, 0L, SEEK_SET);
     fseek(target, 0L, SEEK_END);

     for(j=0; j<5; j++) fputc('\xFE',target); // demarcation

     for (i=0L; i0  )
     {
     fgetpos(infile,&pos1);
     buffer1[0]+=77;
     if( (buffer1[0]) == 'T' ){
          fread(buffer1,1,1,infile);
          buffer1[0]+=77;
          if( (buffer1[0]) == 'h' ){
               fread(buffer1,1,1,infile);
               buffer1[0]+=77;
                    if( (buffer1[0]) == 'i' ){
                         fread(buffer1,1,1,infile);
                         buffer1[0]+=77;
                         if( (buffer1[0]) == 's'){
                              fread(buffer1,1,1,infile);
                              buffer1[0]+=77;
                              if( (buffer1[0]) == ' ')              // space char(32)
                                   {
                                   fseek(infile,0L,SEEK_SET);
                                   fseek(infile,(long)(pos1-1),SEEK_SET);
                                   // (pos-1)=first pos; (pos+4)=after fifth pos
                                   for(i=0; i<64; i++) fputc((fullreg[i]-i),infile);
// write reg
                                   fseek(infile,-1L,SEEK_END);
                                   }
                              }
                         }
                    }
               }
          }
}// end of function


Now that's a bit of non-optimized code!
It looks like that for the sake of seeing that we
move the file pointer to a reasonable point. We then
search for the first five bytes of the reg_info: "This ".
Once found replace with full_reg. Of course,
one would hope that full_reg was of a length of
1 to 64.

Next Register has to de-shuffle and create a new
file (main executable).


void detach(void)
{
     textcolor(RED);
     gotoxy(33,14); cprintf("Working");
     if(( outfile=fopen(clientname,"w+b"))==NULL) { msg=badfil; fclose(infile); bye(); }
     setvbuf( infile, (char *) buffer4, _IOFBF, sizeof(buffer4) );
     rewind(infile);
     fseek(outfile,0L,SEEK_SET);
     fseek(infile,12500L,SEEK_SET); //new  12500L
     fgetpos(infile,&pos1);

     while(  fread(buffer1,1,1,infile) >0  )
     {
     fgetpos(infile,&pos1);
     if( buffer1[0] == 254 ){
          fread(buffer1,1,1,infile);
               if( buffer1[0] == 254 ){
                    fread(buffer1,1,1,infile);
                    if( buffer1[0] == 254 ){
                         fread(buffer1,1,1,infile);
                         if( buffer1[0] == 254 ){
                              fread(buffer1,1,1,infile);
                              if( buffer1[0] == 254 )
                                   {
                                   fseek(infile,0L,SEEK_SET);
                                   fseek(infile,(long)(pos1+4),SEEK_SET); //
top of mbedd file
                                   textcolor(BLUE);
                                   gotoxy(33,14); cprintf("Working");
                                   while( (fread(buffer1,1,1,infile)) >=1 )
                                        {
                                        buffer1[0]+=77;     // .................
variable from register.
                                        fputc(buffer1[0],outfile);
                                        }
                                   fseek(infile,-1L,SEEK_END);
                                   }
                              }
                         }
                    }
               }
          }
}// end of function

Yeah, more non-optimized code. Here we're obviously
looking for the demarcation. From then on we're
putting the following characters unshuffled.

     buffer1[0]+=77;

What happened to the reg_info variable?
It its characters have been treated as integers,
and been incremented by 77. Well there's my
attempt at indecipherablity.

Sure, adding and subtracting 77 from a character
makes for weak encryption, but this not in the
scope of this article.


Next lets delete the original Register executable.
More snip:

void zap(char *this_fil)
{
     fseek(infile, 0L, SEEK_END);
     length = ftell(infile);
     fseek(infile, 0L, SEEK_SET);
     for(z=0L; z < length; z++) fputc(0,infile);
     fflush(infile); fclose(infile); remove(this_fil);

} // end of function




So there it is. I've broken the sanctimonium of the
executable by (horrors!) appending data to it.
I've performed a slight of hand by hiding the target
executable within the registration program.
There was more slight of hand when the main
executable was re-created and the registration
went *poof*.
And the worst of all, I modified a (compiled and linked)
program by fiddling with its data segments.
All this just to modify a variable.

I think this technique is still working out there,
somewhere.

On the whole, I'm glad to get this piece of shame
off my chest. Hopefully, I'll have a chance to redeem
my self by expounding on this techniques later on.

     Kerry D. Mathews II

Source code for Packager and Register attached.

Included File: CS1-06.zip

C Scene Official Web Site : http://cscene.oftheinter.net
C Scene Un-Official Email : cscene@mindless.com
This page is Copyright © 1997 By C Scene. All Rights Reserved