Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Temas relacionados > Seguridad
Registrarse FAQ Miembros Calendario Guía de estilo Temas de Hoy

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 27-03-2007
Avatar de dec
dec dec is offline
Moderador
 
Registrado: dic 2004
Ubicación: Alcobendas, Madrid, España
Posts: 13.114
Poder: 34
dec Tiene un aura espectaculardec Tiene un aura espectacular
Hola,

Gracias Román por interesarte por el tema.

Bueno. Antes de nada voy a corregirme a mí mismo:

Código Delphi [-]
DateToStr(Time)

Eso retorna al paso a "pepe" porque no se hacen las cosas bien, como puede verse. En todo caso debe ser así o así:

Código Delphi [-]
DateToStr(Date)
TimeToStr(Time)

Pero, bueno. Es lo de menos... me disculpo porque me pongo quizás demasiado nervioso sin ton ni son y no me paro a mirar las cosas como debe ser...

Vamos al caso. Dices Román que podría dar otro valor a la variable para eliminar el anterior valor... pero el caso es que creo haberlo intentado y no funciona. Es decir.

Código Delphi [-]

const
  NUMERO_BASE = 123;

function Resultado(numeroBase, claveUsuario: string): string;
begin
  result := numeroBase * Length(claveUsuario);
end;

function CompruebaResultado(claveUsuario, numeroSerie: string): boolean;
begin
  result := ( numeroSerie = Resultado(NUMERO_BASE, claveUsuario) );
end;

A esto puede reducirse el caso. Como puede verse en la función "Resultado" se genera el valor que no debería quedarse en la memoria RAM... necesitamos ese valor para compararlo en la función "CompruebaResultado", pero, no debería permanecer en la memoria más tiempo que el preciso.

Y sin embargo aparece... pero he probado y no vale hacer algo así:

Código Delphi [-]
function CompruebaResultado(claveUsuario, numeroSerie: string): boolean;
var
  s: string;
begin
  s := Resultado(NUMERO_BASE, claveUsuario);

  result := ( numeroSerie =  s);

  s := '';
end;

No; El número de serie sigue apareciendo. Y parece ser que es porque donde deja su "huella" en la memoria RAM es en la propia función "Resultado". Pero claro, aquí si que obviamente no podemos hacer algo como esto:

Código Delphi [-]
function Resultado(numeroBase, claveUsuario: string): string;
begin
  result := numeroBase * Length(claveUsuario);
  result := ''; // No puede ser claro está
end;

Se me ocurre al hilo de escribir aquí que tal vez si en lugar de una función fuese un procedimiento que retornara el "número de serie" en un parámetro pasado por referencia... o sea:

Código Delphi [-]
procedure Resultado(numeroBase, claveUsuario: string; var numeroSerie: string);
begin
  numeroSerie := numeroBase * Length(claveUsuario);
end;

... Tal vez sí que podríamos luego hacer algo así:

Código Delphi [-]
function CompruebaResultado(claveUsuario, numeroSerie: string): boolean;
var
  s: string;
begin
  Resultado(NUMERO_BASE, claveUsuario, s);
  result := ( numeroSerie =  s);
  s := '';
end;

Tengo que probar a ver...
__________________
David Esperalta
www.decsoftutils.com
Responder Con Cita
  #2  
Antiguo 27-03-2007
Avatar de dec
dec dec is offline
Moderador
 
Registrado: dic 2004
Ubicación: Alcobendas, Madrid, España
Posts: 13.114
Poder: 34
dec Tiene un aura espectaculardec Tiene un aura espectacular
Hola,

Muchas gracias Seoane... pero, ¿estás tú seguro de que Pepe no aparece por ahí? ¡A mí no se me va de la memoria!

Edito: Sí que funciona como dices Seoane. Aparece Pepe cuando efectivamente uno quiere comprobar "Pepe", precisamente. Pero si uno trata con "Juan" (es decir, no "valida") entonces "Pepe" no aparece tal cual...

Tengo que tratar ahora de llevar el código al programa que digo, y veremos a ver, porque no termino de comprenderlo... Lo que ya no sé es si probar pasando como parámetro por referencia a Pepe... puesto que la solución que planteas parece más elegante, no sé.
__________________
David Esperalta
www.decsoftutils.com

Última edición por dec fecha: 27-03-2007 a las 13:45:27.
Responder Con Cita
  #3  
Antiguo 27-03-2007
Avatar de dec
dec dec is offline
Moderador
 
Registrado: dic 2004
Ubicación: Alcobendas, Madrid, España
Posts: 13.114
Poder: 34
dec Tiene un aura espectaculardec Tiene un aura espectacular
Hola,

Lamento molestar otra vez... Seoane... he intentado implementar el código (y la idea... dentro de mis posibilidades) en el programa de marras y el asunto no ha funcionado: sigue viéndose en la memoria RAM lo que no debía verse.

Y entonces me he preguntado cómo es posible si he probado tu ejemplo y yo mismo he dicho que me había funcionado... pero lo he vuelto a probar y el asunto no funciona Seoane... y ahora no sé si es que no nos ponemos de acuerdo (sin duda por culpa mía) acerca de lo que hay que quitar y lo que no...

En tu ejemplo, en todo caso (se "compruebe" o no se "compruebe") que el usuario escribió "Pepe"... este sigue apareciendo en la memoria RAM... ¿tú cómo lo ves?

Gracias en todo caso.

PD. Es verdad Román que acaso he proporcionado información de cierta relevancia a alguien... pero no era mi intención: no le dí importancia en ese sentido. No sé si porque doy por supuesto que al final lo explicado no va a servir... si al cabo se consigue eliminar de la memoria RAM el valor de que tratamos.
__________________
David Esperalta
www.decsoftutils.com
Responder Con Cita
  #4  
Antiguo 27-03-2007
Avatar de seoane
[seoane] seoane is offline
Miembro Premium
 
Registrado: feb 2004
Ubicación: A Coruña, España
Posts: 3.717
Poder: 24
seoane Va por buen camino
Si aparece no sera por culpa de la función "Comprobar" sino por culpa de la función "Resultado" que al manipular strings nos provoca el problema. Lo ideal es utilizar solo variables que podamos borrar, ya que delphi aunque libera la memoria que ocupan, no se preocupa de borrar lo que contienen.

Aquí el problema es como planteas la protección, comparar lo que entra el usuario con un valor fijo y devolver un boolean no es muy buen sistema de protección. Funciona, y para un usuario "normal" seria suficiente (1), pero si ya nos encontramos con un "listo" la cosa falla. Saltarse una protección de este tipo es tan fácil como parchear el programa para que la función "Comprobar" siempre devuelva TRUE. Así ya podemos llamar a la función mil veces en nuestro código que la protección ha quedado desactivada.

Pero supongamos que el listo no lo es tanto, y no sabe ensamblador, pero conoce el programa WinHex y prueba a "pescar" en la memoria la posible clave. Pues como la incluyamos como constante en nuestro exe ya estamos vendidos, es mas ni siquiera le haría falta leer la RAM, con solo leer el ejecutable la podría encontrar. Por eso la clave debe generarse durante la ejecución, y utilizarse durante todo el proceso (generación y comprobación) variables que luego podamos borrar. Y lo mas importante, que el listo no sepa ensamblador para que no nos desmonte todo usando lo del párrafo anterior

Si de verdad quieres proteger la aplicación (mas tarde o mas temprano caen todas) tendrías que irte a algo mas "profesional". Lo primero un antidebugger, para evitar que usen un debugger. Luego podemos encriptar parte del código del programa y utilizar como clave la clave del producto, de esta manera si la clave no es correcta no hay manera de obtener el código. Y por ultimo un buen rootkit para vacilarlos nosotros antes de que nos intenten vacilar ellos (Parece una broma, pero recordemos a Sony y alguno mas)

Como ves, si empiezas a preocuparte por lo que van a hacer los "listos" puedes terminar paranoico. Así que si verdaderamente es importante, una llave hardware y no se hable mas.

(1) Para mi también seria suficiente, con tantos programas OpenSource como hay, no pienso perder el tiempo buscando claves.
Responder Con Cita
  #5  
Antiguo 27-03-2007
[basti] basti is offline
Miembro Premium
 
Registrado: ago 2004
Posts: 388
Poder: 20
basti Va por buen camino
Hola, he visto este hilo y me parece interesante. Creo que tanto 'Pepe' como la fecha pueden aparecer en el volcado de memoria del programa de Seoane por dos razones, espero no equivocarme.

'Pepe' está escrito de manera estática en la función Resultado, por lo tanto no hay manera de quitarlo de la memoria. Esto no sería un problema para tu aplicación, ya que la clave del cliente no estaría escrita en el código de la aplicación.

El otro problema que veo es la pila del programa, cuando se hace la siguiente llamada:
Código Delphi [-]
  StrLCopy(Str,PChar('Pepe'+DateToStr(Time)),L);

El valor 'Pepe'+DateToStr(Time) se copia en la pila de llamadas de la aplicación, y permanecerá ahi hasta que otras llamadas sobreescriban estos datos en la pila.

Puedes comprobarlo de la manera siguiente:
En el código de Seoane haces una implementación de StrLCopy, algo así
Código Delphi [-]
Procedure StrLcopy(dest, org : PChar; len : Integer);
begin
  while org^ <> #0 do
  begin
    dest^ := org^;
    Inc(dest);
    Inc(org);
  end;
  dest^ := #0;
end;
de manera que uses esta función en vez de la original de delphi. Pones un punto de ruptura dentro de la función, vas a la ventana "Call Stack". Ahí verás el valor tanto de 'Pepe' como la fecha.

La solución, creo que podría ser una llamada a una función recursiva, justo después de la llamada a StrLCopy, para que sobreescriba la pila. La función debe ser llamada las veces que hagan falta para borrar los datos de la pila. Algo así:
Código Delphi [-]
procedure Resultado(Str: PChar; L: Integer);
  procedure VamosAContarAlReves(n : integer);
  begin
    if n > 0 then
      VamosAContalAlReves(n - 1);
  end;
begin
  // Pues yo si que uso DateToStr ¿que pasa?
  StrLCopy(Str,PChar('Pepe'+DateToStr(Time)),L);
  VamosAContarAlReves(100);
end;

Última edición por basti fecha: 27-03-2007 a las 15:02:22.
Responder Con Cita
  #6  
Antiguo 27-03-2007
Avatar de seoane
[seoane] seoane is offline
Miembro Premium
 
Registrado: feb 2004
Ubicación: A Coruña, España
Posts: 3.717
Poder: 24
seoane Va por buen camino
Ingenioso método de borrar la pila Basti

Entonces ya tenemos los 3 pasos: no usar constantes, borrar las variables y borrar la pila.
Responder Con Cita
  #7  
Antiguo 27-03-2007
Avatar de dec
dec dec is offline
Moderador
 
Registrado: dic 2004
Ubicación: Alcobendas, Madrid, España
Posts: 13.114
Poder: 34
dec Tiene un aura espectaculardec Tiene un aura espectacular
Hola,

Gracias a todos, de verdad. Estaba a punto de escribir esto porque me parecía haber encontrado una posible solución, pero, me quedo corto al lado vuestro.

Como dices Seoane el problema está en manipular variables en la función "Resultado". Si no lo hacemos, es decir, si "calculamos" el resultado ya dentro de la función "StrLCopy" entonces desaparece el problema. Es decir, que puedo decir que el problema está resuelto gracias a vosotros. Acabo de comprobarlo y volverlo a comprobar.

Dices Seoane que dejar el Serial como constante no es buena idea... pero no se hace así. Lo que se tiene como constante es un número "base". Con este número base y la clave del usuario se genera un "Serial", pero esto se hace con cierto algoritmo (luego más sobre esto) que no puede conocerse así como así.

Ahora bien. Parece (y digo parece porque he hecho pruebas pero tengo que hacer alguna más aún) que conseguimos hacer desaparecer el "Serial" correcto de la memoria RAM. Ahora lo que me deja perplejo es el tema de la pila... ¿ya no basta con la memoria RAM? ¿Acaso puede buscarse el "Serial" en la pila incluso cuando digo que ya no aparece en la memoria RAM?

Definitivamente me queda mucho más por aprender de lo que aprenderé nunca.

Para quien esté interesado, estoy utilizando una clase para todo esto que está basada en el componente "JvSerialMaker" de la Jedi Library. Evidentemente ya sabéis que este componente "deja" en la memoria RAM el número de serie que genera y puede comprobar...

En fin voy a asegurarme con más pruebas de que el número de serie no aparece en la memoria RAM y luego acaso me ponga con el tema de la pila que apunta el compañero basti (gracias basti). Pero estoy de acuerdo con Seoane... probablemente estas cosas habría que tomarlas bastante más en serio de lo que estoy dispuesto a hacer para evitar que alguien "piratee" un programa como se empeñe en hacerlo...
__________________
David Esperalta
www.decsoftutils.com
Responder Con Cita
  #8  
Antiguo 27-03-2007
Avatar de Neftali [Germán.Estévez]
Neftali [Germán.Estévez] Neftali [Germán.Estévez] is offline
[becario]
 
Registrado: jul 2004
Ubicación: Barcelona - España
Posts: 18.339
Poder: 10
Neftali [Germán.Estévez] Es un diamante en brutoNeftali [Germán.Estévez] Es un diamante en brutoNeftali [Germán.Estévez] Es un diamante en bruto
Veo que habéis avanzado en el tema mientras yo escribía, o mejor dicho, me enrollaba...

Cita:
Empezado por dec
Ahora lo que me deja perplejo es el tema de la pila... ¿ya no basta con la memoria RAM? ¿Acaso puede buscarse el "Serial" en la pila incluso cuando digo que ya no aparece en la memoria RAM?
Como he comentado más arriba, no debería estar ni en la pila ni en los registros; Y eso significa que no se puede asignar a una variable, que no se puede pasar como parámetro y no debe ser devuelto por ninguna función (hablamos del serial correcto completo).
__________________
Germán Estévez => Web/Blog
Guía de estilo, Guía alternativa
Utiliza TAG's en tus mensajes.
Contactar con el Clubdelphi

P.D: Más tiempo dedicado a la pregunta=Mejores respuestas.
Responder Con Cita
Respuesta



Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

El código vB está habilitado
Las caritas están habilitado
Código [IMG] está habilitado
Código HTML está deshabilitado
Saltar a Foro

Temas Similares
Tema Autor Foro Respuestas Último mensaje
eliminar datos con dbgrid UREÑA Conexión con bases de datos 20 30-03-2007 23:41:32
Eliminar Datos eficientemente k_rito Conexión con bases de datos 5 27-11-2006 00:44:45
Cómo obtener ciertos datos de los archivos ejecutables y librerías StartKill Varios 1 14-08-2006 23:10:01
Eliminar del memoria los querys Aura OOP 4 01-04-2004 17:40:40
Eliminar datos de una tabla DBF vicvil Tablas planas 4 16-05-2003 21:17:46


La franja horaria es GMT +2. Ahora son las 06:16:13.


Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi
Copyright 1996-2007 Club Delphi