02 septiembre 2009

El componente mxProtector (2)

Vamos a continuar viendo otros modos de protección de este componente como pueden ser la limitación por número de días y por medio de licencias mediante un generador de claves.

PROTECCIÓN POR NÚMERO DE DÍAS TRANSCURRIDOS

Debemos configurar el componente mxProtector de este modo:

1º Dentro de su propiedad Options activamos las opciones poAutoInit, poCheckSystemTime y poPasswordOnce:

2º En su propiedad Protection Types debemos activar stDayTrial:

3º También debemos poner en MaxDayNumber el número de días que damos de plazo, por ejemplo 30.

3º En su evento OnDayTrial podemos el código que controla el paso de cada día:

procedure TFPrincipal.mxProtectorDayTrial(Sender: TObject;
DaysRemained: Integer);
begin
if DaysRemained = 1 then
ENumDias.Caption := 'Sólo te queda un día'
else
ENumDias.Caption := Format('Te quedan %d días.', [DaysRemained]);

BReiniciar.Enabled := False;
end;

4º En su evento OnExpiration va el código cuando ya no quedan más días:

procedure TFPrincipal.mxProtectorExpiration(Sender: TObject);
begin
ENumDias.Caption := 'Le quedan 0 días. Su licencia ha expirado';
BReiniciar.Enabled := True;
end;

5º Y en su evento OnInvalidSystemTime podemos el mensaje que muestra que el usuario ha intentado mover hacia atrás la fecha de Windows para estirar la licencia:

procedure TFPrincipal.mxProtectorInvalidSystemTime(Sender: TObject);
begin
Application.MessageBox('La hora de tu sistema no es correcta.',
'Su licencia ha expirado', MB_ICONSTOP);
end;

6º Al pulsar el botón Reiniciar volvemos a darle otros 30 días:

procedure TFPrincipal.BReiniciarClick(Sender: TObject);
begin
mxProtector.Reset;
end;

Y al igual que vimos en el ejemplo anterior de control por número de ejecuciones, podemos implementar los métodos OnGetString, OnPutString, OnGetBoolean y OnPutBoolean para que guarde el estado en la clave de registro que queramos o en un archivo INI, binario, etc. Esto es válido para todos los métodos de protección que hemos visto así como los siguientes que voy a comentar.

PROTECCIÓN POR REGISTRO DE NÚMERO DE SERIE

Esta es otra de las protecciones que más se suelen utilizar para distribuir programas con licencia Shareware. Según el nombre del usuario, un ID que haga único al PC y un número de serie podemos proteger cada licencia para que sólo se ejecute en un equipo.

Lo primero que vamos a hacer es el programa que va a registrar el usuario según un número de serie que nos dará un generador de claves que vamos a crear más adelante.

El programa va a tener este formulario:

Veamos como configurar el componente mxProtector igual que hemos visto anteriormente:

1º En la propiedad Options debemos activar las opciones poAutoInit, poCheckSystemTime, poPasswordOnce y poUseHardwareKey:


2º Activar en la propiedad ProtectionTypes el valor stRegister:


3º En el evento OnGetSerialNumber le pasamos al componente el nombre del usuario y el número de serie generado:

procedure TFPrincipal.mxProtectorGetSerialNumber(Sender: TObject;
var UserName, SerialNumber: string);
begin
UserName := Usuario.Text;
SerialNumber := NumSerie.Text;
end;

4º En el evento OnInvalidSerialNumber mostramos el mensaje de error en caso de que sea incorrecto:

procedure TFPrincipal.mxProtectorInvalidSerialNumber(Sender: TObject);
begin
Application.MessageBox('Nº de serie incorrecto',
'Consulte con el proveedor', MB_ICONSTOP);
end;

5º En el evento OnUnknowHardware debemos mostrar un mensaje en caso de que no podamos obtener la ID del PC:

procedure TFPrincipal.mxProtectorUnknownHardware(Sender: TObject);
begin
Application.MessageBox('El hardware de este equipo es incompatible con este software.',
'Consulte con el proveedor', MB_ICONSTOP);
end;

6º Al pulsar el botón Registrar activamos el producto:

procedure TFPrincipal.BRegistrarClick(Sender: TObject);
begin
mxProtector.Registration;
ComprobarRegistro;

if mxProtector.IsRegistered Then
begin
Application.MessageBox('Gracias por comprar el producto',
'Registro realizado', MB_ICONINFORMATION);
end;
end;

El procedimiento de comprobar el registro es el siguiente:

procedure TFPrincipal.ComprobarRegistro;
begin
if mxProtector.IsRegistered then
begin
Caption := 'Programa registrado';
BRegistrar.Enabled := False;
BDesinstalar.Enabled := True;
end
else
begin
Caption := 'Programa no registrado';
BRegistrar.Enabled := True;
BDesinstalar.Enabled := False;
end;
end;

Activamos o desactivamos los botones de registrar o desinstalar así como el título del formulario según este registrado el programa o no.

7º A pulsar el botón Desinstalar desinstalamos la clave de registro:

procedure TFPrincipal.BDesinstalarClick(Sender: TObject);
begin
mxProtector.Reset;
Application.MessageBox('Ya puede desinstalar del producto',
'Registro cancelado', MB_ICONINFORMATION);
ComprobarRegistro;
end;

8º Por último, tenemos que comprobar en el evento OnCreate del formulario si hemos registrado el programa y obtener ID del PC:

procedure TFPrincipal.FormCreate(Sender: TObject);
begin
ID.Text := mxProtector.GetHardwareID;
ComprobarRegistro;
end;

CREANDO EL GENERADOR DE CLAVES

Ahora vamos a hacer un programa que genere números de serie según el nombre del usuario y un ID único del PC (número de serie del disco duro, de la tarjeta de Windows, etc.).

El programa va a tener este formulario:

Veamos como configurar el componente mxProtector para este programa:

1º En la propiedad Options debemos activar las opciones poAutoInit, poCheckSystemTime, poPasswordOnce y poUseHardwareKey:


2º Activar en la propiedad ProtectionTypes el valor stRegister:

3º En el evento OnGetHardwareID nos encargamos de pasarle al componente el ID del equipo:

procedure TFPrincipal.mxProtectorGetHardwareID(Sender: TObject;
var HardwareID: string);
begin
HardwareID := ID.Text;
end;

4º El botón Generar le pedimos al componente que nos genere un número de clave según el usuario y el ID del PC:

procedure TFPrincipal.BGenerarClick(Sender: TObject);
begin
NumSerie.Text := mxProtector.GenerateSerialNumber(Usuario.Text);
end;

Vamos a probar ambos programas. Abrimos primero la aplicación:

Copiamos la clave que nos ha dado el programa, abrimos el generador de claves y escribimos nuestro nombre completo y el ID generado por el programa. Después pulsamos el botón Generar y nos dará la clave de registro:

Ahora copiamos la clave de registro, la llevamos al programa, introducimos nuestro nombre y pulsamos el botón Registrar:

Si cerramos la aplicación y volvemos a abrirla veremos que el programa ya está registrado. Podemos quitar la licencia pulsando el botón Desinstalar que dejará el programa como al principio.

Aunque parezca algo complicado, si tuviésemos que hacer todo esto a mano habría que escribir mucho más código. En el próximo artículo seguiremos viendo otros modos de protección.

Pruebas realizadas en RAD Studio 2007.

20 comentarios:

JOYST1CK dijo...

Buenas... pues yo me he encontrado con el primer problema...

Siguiendo todos los pasos no consigo que funcione la opcion de registrar siempre me dice que el nº de serie es invalido...

Incluso he probado con los programas Demo que se incluyen con el componente, he compilado el "KeyGenerator" y el "Registration" de los ejemplos, los ejecuto e intento registar el demo con el serial que me genera el KeyGenerator y me sigue diciendo que el nº de serie es incorrecto, ¿ que cosa mas rara no ? no he modificado nada de los demos, solo los he compilado, estoy utilizando RAD Studio 2009 y la version 1.32 del componente mxprotector...

Voy a probar en el portatil a ver si ahi funciona... :S

JOYST1CK dijo...

Bueno ya se mas o menos porque no funciona, la solucion ni idea pero el porque es por el RAD Studio 2009...

Si instalo el componente en Delphi 6 y compilo las demos de KeyGenerator todo funciona bien, ahora si lo compilo en el 2009 siempre me dice que el nº de serie es invalido :(

Pues nada un pasito para adelante y dos para atras...

Si alguien consigue hacerlo funcionar con el 2009 que me avise por favor :(

Administrador dijo...

Ya suponía yo que era de eso. Todos los componentes que he traído de otras versiones de Delphi a Delphi 2009 han sido un completo desastre, incluso aunque compilen bien.

Eso se debe ha que han cambiado el tipo base string a unicode, lo que ha creado un terremoto de incompatibilidad hacia atrás impresioante.

Deberían haber creado un tipo string unicode llamado por ejemplo UString que no hubiese afectado al núcleo de Delphi. Todas estas tonterías se pueden hacer en .NET ya su núcleo esta preparado para ello, pero en Win32 es suicida.

Por ello, sólo utilizo componentes el Delphi 2009 cuando están desarrollados y compilados exclusivamente para esta versión.

Así que mucho cuidado porque puede dar muchos sustos. Por ahora seguiré escribiendo artículos en Delphi 2007 ya que por lo menos es más estable en este sentido.

Saludos.

JOYST1CK dijo...

Me lo estaba imaginando pero como en la web de max dice que es compatible con 2009 pues crei que al menos lo habian probado xDDDDDDDDDDD

Nada empezare a instalar componentes en la 2007, me toca mudarme otra vez, llevo 2 semanas probando la 2009 y solo encuentro problemas con el unicode de las narices...

Ademas le habia cogido cariño al protector este, si funcionase seria todo mucho mas facil...

Gracias Admin :D

Un Saludo

JOYST1CK dijo...

Creo que he conseguido que funcione en D2009, para ello he cambiado las propiedades del mxProtector Options->poUseHardwareKey a False y Options->poUniqueHardwareKeyID a True, cambiando estas propiedades tanto en la aplicacion como en el generador de llaves si consigo que funcione :D

Gracias y seguire tus articulos para aprendar más opciones de este componente :D

Un Saludo

JOYST1CK dijo...

Si funciona si, pero el nº de serie lo genera basandose SOLO en el UserName, el nº de id de la maquina le da igual, lo que significa que puede ser registrado en mas de una maquina con ese serial....

Bueno algo es algo :(

Anónimo dijo...

Ya encontre la solucion al mensage que sale aun cuando se ha generado la clave correcta.. para mayor informacion pregunte en kr_spartan@hotmail.com y con gusto les doy la solucion...

Anónimo dijo...

Y cual es la gracia?? Mejor compartelo con todos :)

JOYST1CK dijo...

Ya estube hablando con el pero su solucion no funciona en d2009 ni d2010...

Carles Vidal dijo...

Hola he probado los dos ejemplos pero el programa para registrar me funciona ejecuandolo con delphi 2007 pero cuando ejecuto con el .exe creado me pone el error "Failed to set data for R1"
Alguien se ha encontrado con este problema ?
Gracias

Administrador dijo...

Revisa bien los eventos donde guardas los datos binarios o cadenas de texto.

Son los responsables del error que te da (OnGetString, OnGetBoolean, OnPutString y OnPutBoolean).

Saludos.

Helard Flores dijo...

Hola administrador, sigo cada uno de tus post a menudo, ahora estuve probando el componente mxprotector, y se me ocurre que hay una forma de vulnerar la proteccion facilmente, si yo genero una proteccion de la forma que esta en el ejemplo.
Quiere decir que con el mismo aplicativo es el crack, si alguien tiene algun conocimiento de este componente.
No hay alguna forma de que al componente se le asigne una especia de llave unica a partir de la cual genere el serial, para de esta manera sea mas dificl vulnerar nuestra aplicacion?.

Gracias de antemano por tu respuesta.
saludos

Administrador dijo...

El componente mxProtector es para hacer una protección básica de licencia cuando se la vas a poner a un cliente que no tiene ni idea de informática.

Pero si pretendes distribuir y vender un programa por internet entonces no tienes nada que hacer. Te lo van a desproteger en 5 minutos.

Para crear protecciones profesionales hay que utilizar soluciones como armadillo o esas llaves de USB que vienen codificadas. Aún así, ninguna solución es perfecta y es cuestión de tiempo que lo revienten.

Tu fíjate en Windows 7, las herramientas de Embarcadero, las de Adobe, Corel, etc. No queda una viva. Creo que el futuro pasa por software libre o gratuito cobrando solo por servicios a medida.

Así es la dura vida de un programador.

Helard Flores dijo...

Tienes mucha razon al respecto, Gracias por tu comentario, averiguare un poco mas sobre este componente seria magnifico que se pudiera ingresar una cadena tipo semilla, para que apartir de esta raiz con el nombre y el id del hardware generar el serial, asi seria un poco mas trabajoso averiguar esta semilla. y de ahi el serial. Felicitaciones por tus aportes, sigue adelante y Dios te bendiga.
saludos

santiago dijo...

Perdon por llegar tarde .. :)

una posible solucion a la falta de poder poner una "semilla" para la generacion del key :
(pregunto) podria ser usar el dato username como id de Apliacion, es decir usarlo de manera interna en el sistema y mostrarle al usuario solo el hardwareid , con el cual sumado al id de apliacion (que solo nosotros sabemos) generarle el codigo de activacion ?

o estoy errado en lo que estoy diciendo?

muy bueno el blog.

Administrador dijo...

En eso tienes razón, podemos invertar cualquier generador de ID única ya sea por el número de serie de cualquier dispositivo de hardware o como hago yo con el nº de serie de la unidad C: con que se ha formateado.

Todo vale para despistar a los hackers con algo original.

Saludos.

Helard Flores dijo...

Hola,
tengo una aplicacion en clx, he querido usar el componente, para un registro con numero de serie de acuerdo al ejemplo, ejecuta bien, pero con la clave generada no lo registrar, siempre sale que la serie es invalidad,
si alguien me puede ayudar, quizas hay que usar de forma diferente en clx.
gracias

Unknown dijo...

Hola, buenos días.
Mi nombre es Rubén.
Estoy tratando de trabajar con la componente MaxProtector pero me ocurre como a Carles Vidal.
Uso w7 y D7. Como es lógico instalé el dpk D7. La aplicación trabaja correctamente cuando se compila y la estamos operando desde el IDE, pero cuando se trata de ejecutar el .exe generado por Delphi aparece la alarma "Failed to set data for R1" en mi caso.
Compile todos los ejemplos y ocurre lo mismo trabajan bien en el IDE pero presentan la falla de, al parecer, escritura de datos en el registro para todos los ejemplos.
Probé los .exe en otra PC con w10 y ocurren las mismas alarmas.
¿Alguna idea, por favor?
Gracias anticipadas

Helard Flores dijo...

Hola, prueba ejecutando como administrador la primera vez, en w10 se debe ejecutar siempre como administrador.

Espero te ayude.

Unknown dijo...

Muchas gracias Helard Flores por tu respuesta.
Efectivamente, cuando ejecuto los demos compilados como administrador funcionan bien pero cuando los vuelvo a ejecutar normal (no como Administrador) me dan el mismo error tanto en W7 como en W10.
Y claro no debes instalarle un programa a un cliente y decirle que solo vale para el administrador, un poco feo, no?
La excepción se produce cuando trata de escribir en la clave T3 ("Reg.WriteString( sKey, sValue"); en la linea 686 de la Unit mxProtector.
¿por que como administrador si escribe en el registro y no como usuario normal? La respuesta es la solución.
¿Alguna otra idea?
Gracias

Publicidad