FTP | CCD | Buscar | Trucos | Trabajo | Foros |
|
Registrarse | FAQ | Miembros | Calendario | Guía de estilo | Temas de Hoy |
|
Herramientas | Buscar en Tema | Desplegado |
#21
|
||||
|
||||
Cita:
Lo siguiente es evitar comparaciones directas; Simplemente, porque no siempre se necesita encontrar el Serial, a veces basta con "Parchear". Es decir, si yo no encuentro el Serial, pero veo tres comparaciones que dicen: En este caso optaría por "parchear" los tres != por tres =. Ya se que el tema se va complicando, pero son cosas que hay que tener en cuenta; La mayoría de sistemas anticopia (serios) ya hechos tienen en cuenta estas cosas y muchas más... En ese caso a la hora de comparar dos valores, podemos utilizar por ejemplo la resta para saber si da cero, funciones del tipo CHAR y Ord (aplicándolas a los dos) para no comparar los valores exactos, sumar y restar a ambos un valor,... Aunque desde delphi parece una tontería hacer esto:
Para el que está revisando el código en ensamblador supone uno o varios saltos, cosa que dificulta mucho a la hora de seguir el código (las llamadas a funciones); Pensad que si se van aplicando diferentes a cada comparación, al final la cosa se hace muy compleja para el que está revisando la pila y los registros.
__________________
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. Última edición por Neftali [Germán.Estévez] fecha: 27-03-2007 a las 18:30:48. |
#22
|
||||
|
||||
Cita:
Llegados a este punto, creo que el menor de los problemas sería el como ocultar la forma y el modo de como cotejar una clave, dado que llegados a ese nivel y si resulta de interés, el invasor no se iba a preocupar de la clave, sino que se preocuparía de ver cual es el procedimiento que le hace salir del programa (por ejemplo) y que otras alternativas o saltos de programa tiene para que este funcione adecuadamente, para a continuación parchear y a disfrutar.... Creo yo...
__________________
Un poco de tu generosidad puede salvar la vida a un niño. ASÍ DE SENCILLO |
#23
|
||||
|
||||
Una pregunta en cuanto al borrado del dato:
¿Qué no puede usarse simplemente una variable global y asignarle otro valor? No hay stack donde quede nada y la variable se ha reescrito. // Saludos |
#24
|
||||
|
||||
Cita:
__________________
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. |
#25
|
||||
|
||||
Una vez participé en un proyecto de "seguridad" para evitar que "piratearan" los programas de la empresa donde trabajaba. Tuvimos en cuenta lo que habéis comentado y un montón de cositas más, el proyecto duró 7 meses y éramos 3 personas dedicadas únicamente a eso, en su día tuvo un presupuesto de 60.000 euros. Buscamos información de todos los métodos conocidos hasta la fecha, documentos, libros, consultas a algunos expertos, etc.
Entre nosotros había uno, no era yo, que decía constantemente: "no vale la pena tanto tiempo y dinero en protegerlo, lo mejor es que lo copien y lo usen aunque sea gratis y que no use el de la competencia". Pues bien, a la semana de sacar el programa, un chaval ruso que además nos envió un gracioso email, publicó un keygen para el programa, que además de ser más simple que nuestro propio programa, era más rápido, pequeño, cómodo y seguro. Nos quedamos con la boca abierta, nos miramos los unos a los otros y pensamos: "¡¡¡cómo podemos ser tan malos programadores!!!". Moraleja: sin comentarios |
#26
|
|||
|
|||
Cita:
Aqui en Mexico diriamos, "para chingon, chingon y medio". Salud OS.
__________________
"La forma de empezar es dejar de hablar y empezar a hacerlo." - Walt Disney |
#27
|
||||
|
||||
Me voy a meter a cracker. Recordáis la protección de la que hablaba con el md5, esa tan maravillosa, pues con el OllyDbg del que hablaba Neftali me la salte en un momento, el tiempo que me llevo averiguar como guardar los cambios en ese programa endemoniado
La cosa fue tan sencilla como cambiar esto: Código:
00459BF2 |. E8 4DCAFAFF CALL <JMP.&kernel32.CompareStringA> 00459BF7 |. 83E8 02 SUB EAX,2 00459BFA |. 85C0 TEST EAX,EAX Código:
00459BF2 |. E8 4DCAFAFF CALL <JMP.&kernel32.CompareStringA> 00459BF7 B8 00000000 MOV EAX,0 00459BFC |. 0F94C0 SETE AL |
#28
|
||||
|
||||
Hola,
Muchísimas gracias a todos por vuestro interés en el asunto que planteo en este Hilo. Voy a tratar de continuar respondiendo a lo que se ha comentado en mi ausencia. Román, dices de hacer uso de una variable global en donde se almacenaría el número de serie correcto (generado en el programa) para compararlo con el introducido por el usuario. Acto seguido habría que dar a dicha variable global otro valor. ¿Pero esto funcionaría? Lo digo porque esta mañana comprobé que el número de serie correcto (insisto, generado en el propio programa) aparecía en la memoria incluso cuando este no era albergado en ninguna variable. O por mejor decir, el algoritmo que construye el número de serie correcto ofrecía su resultado a la propia función ("StrLCopy") encargada de copiarlo a cierta variable... que era ¿liberada? de la memoria acto seguido de utilizarla. Es decir, que parece que sólo conque el número de serie sea generado este ya aparecerá completo en la memoria... o eso se deduce de las pruebas que he llevado a cabo, si omitimos el echo de que no llegué a hacer uso de las funciones que propuso el compañero basti más arriba. Tal vez esto último es algo que tendría que comprobar antes de nada. Seoane, dices de utilizar un "hash", de comparar el "hash" del número de serie con el introducido por el usuario. Y dices que podríamos guardar dicho "hash" incluso en una constante, puesto que, como bien dices, del "hash" no se puede colegir el número de serie. Es cierto, pero, también lo es que no podemos guardar el número de serie correcto como una constante, sencillamente, porque este no es un valor constante: no hay un número de serie correcto para todos y con el que podamos comparar los intentos del usuario. De hecho el número de serie ha de generarse por el propio programa, a partir de un número base y una clave de usuario. Es decir, un número de serie se "calcula" a partir de la clave de un usuario. Sin conocer esta última no es posible generar el número de serie correspondiente. Entonces, si al cabo hay que generar el número de serie (para luego obtener su "hash"), ¿no estaríamos en el mismo problema en que estamos? Es decir, a partir de que podamos calcular el "hash" de un número de serie quiere decirse que habremos generado dicho número de serie... y ya estará en la memoria... o me equivoco. Casimiro, dices que acaso no merezca la pena trabajar en estos menesteres, y puede que lleves razón. Es algo que me he planteado también. Liberar el programa, adjuntar incluso su código fuente, y, bueno, que quien quiera pueda realizar una donación o "algo" para que uno (que trabaja en el programa) se vea compensado de algún modo. El problema es este, precisamente: que uno se quiera ver recompensado, es decir, que no se vea así ya. De hecho como digo es una opción más la de liberar el programa, hacer innecesario el uso de ningún número de serie y aquí paz y después que salga el sol por donde salga. Sin embargo ahora mismo esto que se trata en este Hilo es más bien una especie de reto: se plantea un problema y quiere encontrarse su solución. Independientemente de que en el futuro se quite el problema del medio (y no haya que buscarle solución) lo cierto es que no quisiera evitar el problema... es decir quitarle del medio sin saber antes que al fin y al cabo es algo que tiene solución o soluciones. No digo que tú quieras deshacerte del problema, o no lo digo en ese sentido: creo que sé por dónde vas y ya digo que en cierto modo estoy bastante de acuerdo contigo. Continúo. Veo que antes de publicar esto Seoane ha conseguido "romper" su propia protección... Aunque no de la misma forma en que yo he propuesto, es decir, según yo aunque comparemos "hashes" el número de serie ha de calcularse en el programa y pasará a poder verse en la memoria con un programa como WinEx. Se verán los "hashes" y no se podrá hacer nada con ellos, de acuerdo, pero también se verá el número de serie, si no estoy metiendo la pata con mi planteamiento, claro está. Y esto me hace pensar que acaso logre solucionar el problema que me ocupa pero todavía pueda obtenerse un número de serie válido o a lo menos evitar el registro del programa. Probablemente esto sea así. Pero ahora me preocupa cómo quitar el número de serie de la memoria RAM. Si luego hay otros modos o no los hay de saltarse la protección del programa... eso se verá en su momento llegado el caso. Habéis hablado también (Neftalí mayormente) de que el programa no debería dejar ver a las claras que ha sido o no registrado correctamente. De hecho así es. En el caso del programa que nos ocupa es el usuario quien se encarga de abrir el diálogo para registrarlo. En este diálogo (formulario) el usuario ha de proporcionar su clave de usuario y su número de serie. Si el registro es correcto... no pasa nada, aparentemente. Si es equivocado, tampoco damos al usuario ninguna señal de que el programa no se ha registrado correctamente. La advertencia de que el programa no está registrado digamos que se produce cuando el usuario ejecuta ciertas acciones. Vale que alguien que sepa de estas cosas puede tratar de localizar el "salto" de dicha advertencia, y quitarla del medio antes de que aparezca. Esto seguramente puede hacerse. También es verdad que yo podría tratar de complicar un poco las cosas. Es decir, en lugar de avisar con una advertencia al usuario de que el programa no está registrado... tal vez podría además hacer que mientras el programa lleva a cabo alguna de sus acciones (o varias de ellas) se compruebe su registro y "salte" en el momento. Esto haría las cosas más complicadas al "cracker"... porque en lugar de evitar una advertencia tendría que evitar más de una, y además no sabría, hasta que no lo pudiera comprobar por sí mismo como usuario del programa, cuántas advertencias existen, y dónde existen. Pero en fin, como he dicho, comprendo que alguien con los suficientes conocimientos y la paciencia de rigor conseguiría saltarse las advertencias que se le pusieran por delante: no soy yo mejor que los que diseñan la protección de Windows, por ejemplo, y esta siempre acaba "saltándose" de varias formas además... Pero me preocupa ahora lo del número de serie. Cómo demonios hacer que un dato que conocemos tras un cálculo en el programa, y que luego utilizamos, sin embargo desaparezca de la memoria, no deje rastro alguno y no pueda ser averiguado, por lo tanto. Esto es lo que me preocupa ahora. Y después de escribir todo esto (aunque estanto un poco dormido aún) sigo pensando en que una posible solución puede ir por donde Neftalí apunta: tal vez generar "trozos" del número de serie, y comparar estos trozos con sus correspondientes pares. De este modo seguirían viéndose trozos del número de serie correcto en la memoria, pero, ya complicaría el asunto bastante, puesto que a ver cómo y de qué manera se pone uno a "juntar" los trozos a poco que sean unos cuantos... se me hace que el "cracker" tendría entonces que tirar por otro camino y desde luego no podría obtener el número de serie "completo", mondo y lirondo, de la memoria ocupada por el programa. Bueno. No sé. Digo que lo de partir el número de serie correcto en trozos podría funcionar, pero, lo cierto es que aún no sé cómo llevar a cabo esto. Se admiten ideas y sugerencias y yo por mi parte os mantendré informados en caso de avanzes o retrocesos en este sentido. Otra vez muchas gracias a todos por vuestro interés. Y disculpad el rollazo. |
#29
|
||||
|
||||
Hola,
Otra vez yo... acabo de probar con el método que apuntó primero Seoane, añadiéndole la función recursiva que el compañero basti propuso a su vez, pero, que si quieres arroz Catalina... sin utilizar variables, dejándolo en un "buffer" que acto seguido es liberado de la memoria, haciendo uso luego de la función "VamosAContarAlReves"... ¡que si quieres arroz Catalina! Algún modo ha de haber, digo yo, ¿no? |
#30
|
||||
|
||||
No entendí esto último. ¿Funcionó o no?
// Saludos |
#31
|
||||
|
||||
Hola,
No Román; no me funcionó. |
#32
|
||||
|
||||
Pues es raro. Yo hice una tímida (e ingenua) prueba así: dado que el problema era que el dato se pasaba al stack al pasar el parámetro, supuse que bastaba llamar una segunda vez al procedimiento con un valor "borrador": Resultado('XXXXXXX'),
pero el condenado pepe seguía ahí. Además de que el pepe entra en un Edit, y ése también contribuye, aún borrando el edit, me parece que pepe sigue ahí. // Saludos |
#33
|
||||
|
||||
Hola,
Pues sí. La verdad es que estoy más perdido que un pavo en un garaje. Alguna forma ha de haber de lograr hacer desaparecer de la memoria el número de serie correcto una vez utilizado por el programa. Pero a mí personalmente no se me ocurre ahora mismo ninguna, y es que todo esto de la pila, el stack, la memoria RAM, etc., etc., es nuevo para mí, lo reconozco, siempre me he movido en otro nivel... para mi mal, probablemente. |
#34
|
||||
|
||||
¿Y por qué no 'escondes' a Pepe?, un xor a nivel de bits, por decir algo, para que no se sepa qué es, quedarán caracteres 'extraños'.
|
#35
|
||||
|
||||
Cita:
__________________
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. |
#36
|
||||
|
||||
Cita:
En lugar de borrarlo, que no aparezca. Tal vez me he perdido algo, pero creo que es posible... Se trata de hacer el cálculo sin asignar el SN en ningun sitio. Por ejemplo, este programa; He seguido los pasos (con el WinHex) para encontrar en Serial Correcto en memoria y yo no lo veo. El procedimiento de cálculo es el siguiente:
Como véis es muy "cutre", pero el número correcto no se asigna.
__________________
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. |
#37
|
||||
|
||||
Dista mucho de ser infalible (1) y (2), pero creo que la solución puede ir por aquí.
(1) Comprobación de la longitud. (pepito + palotes); Se pueden ver los registros con los valores 7 y 6 (de ambas longitudes), la resta y la comparación con 2. (2) Comprobación de caracteres 1 a 1. (1234 + casaca); Se puede ver cómo empieza a comparar "1" y "c" y el salto que nos lleva al mensaje de fallo. Creo que la idea es buena.
__________________
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. |
#38
|
||||
|
||||
Hola,
No lo cojo Neftalí. En tu anterior ejemplo (que te agradezco) según se ve en el código puede registrarse el programa con el usuario "pepe" y el número de serie "pepeSN". Claro que lo sé porque tengo acceso al código fuente, en esto estamos de acuerdo. Yo comprendo que ha de haber alguna forma de hacer lo que necesito, puesto que hay programas que me consta no caen en la "trampa" en la que cae el mío. Sin embargo por más que lo intento aún no consigo resultados. Ten en cuenta que no se trata de comparar el valor "clave de usuario" y "número de serie". Se trata de que a una clave de usuario dada le corresponde un número de serie. El programa se encarga, a partir de la clave de usuario y un número "base", se encarga, digo, de generar el número de serie. Yo tengo el programa y un generador de números de serie, que es otro programa. Ambos comparten la unidad "GenerarSerial" y en esta unidad hay una clase con dos métodos: "CompararSerials" y "GeneralSerial". Cuando ejecuto el generador lo que estoy haciendo es obtener un número de serie según la clave de un usuario. El usuario me escribe: "Oyes David, este programa está molón, acabo de ingresarte en tu cuenta 1.000.000 de dólares, espero que sea suficiente para que me envíes un número de serie a nombre de "Pepe Rico". Yo cojo el Generador e introduzco el número base del programa y la clave de usuario "Pepe Rico". El Generador me genera (toma ya) un número de serie para esa clave y ese número base y yo se lo mando a Pepe Rico: "Hola Pepe, recibido el millón ahí te va el número de serie". El programa (ya no el Generador de "Serials"), cuando Pepe Rico introduzca su clave de usuario y su número de serie podrá comprobar si este último se corresponde con el que tiene que ser puesto que podrá calcular (como el Generador) el correcto en base al número base y a la clave de usuario introducida. Hasta ahí bien. Todo es correcto. ¿Todo? No. Porque que el Generador deje en memoria el número de serie correcto no importa. De hecho tiene que ofrecerme ese número de serie correcto, tiene que dejarme "copiarlo" (de hecho se muestra en un "TEdit") para que yo pueda mandárselo a Pepe Rico que para eso pagó el millón de rupias. Ahora bien, el programa, el de Pepe Rico, no el Generador, no debe (y no lo hace) mostrar el número de serie correcto al usuario... ¡pero este se queda en la memoria! Y tal vez Pepe Rico no, pero algún otro usuario conseguirá el número de serie correcto a poco que eche un vistazo... Lo último que he probado ha sido el "CheckSum", el "hash" del número de serie, pero es que no salimos del problema: Yo puedo comparar el "CheckSum" del número de serie del usuario y del correcto, pero si puedo hacer esto último es porque he generado el número de serie correcto, y, según parece, a poco que esto se haga y se haga donde se haga ya aparecerá en memoria... irremediablemente. Tal vez es que el planteamiento es el equivocado. Ya digo que todo mi "sistema de generación y comprobación de números de serie" se basa en el código del componente "TJvSerialMaker" de la Jedi VCL. Pero entonces es que todo programa que haga uso de este componente está comprometido en lo dicho: mostrará el número de serie correcto en la memoria. Tal vez sea esto y no tenga remedio porque es un mal planteamiento o no está lo suficientemente pensado o simplemente es algo sencillo, de andar por casa, puesto que a Pepe Rico probablemente no mirará la memoria RAM ni sabrá siquiera que algo así existe y se puede mirar... ¡Arrggggggggggggggggggggg! |
#39
|
||||
|
||||
Si no es mucho preguntar, como generas el numero de serie. Puede que el problema resida ahí. Podríamos intentar crear un algoritmo, una sola función, que permita comprobar el numero de serie dejando la memoria limpia.
En resumen, muestranos el algoritmo |
#40
|
||||
|
||||
Hola,
Ningún problema Seoane... es de dominio público... ya digo. Extraído de la unidad "JvSerialMaker.pas" de la Jedi Library. De hecho copiaré aquí los dos métodos principales... el que genera números de serie y el que compara un número de serie con el "correcto" (generado)...
Como se ve se parte de un número "base" que ha de ser constante tanto en el programa generador de números de serie como en el programa a "proteger"... Ambos programas, pues, comparten el código anterior. A partir del número base y de una clave de usuario, como puede verse el primer método genera un número de serie: justamente el que corresponde a la clave de usuario + número base. Así se consigue que tanto el programa generador de números de serie como el programa a "proteger" puedan obtener de una clave de usuario un número de serie, el mismo que ha de compararse con el que el usuario introduzca. Todo esto funciona correctamente, si no fuera porque el número de serie correcto (y justo el cuando se genera en el primer método) queda en la memoria. Y es en el primer método donde queda el número en memoria, porque puede verse que en el método el número de serie se va generando "a trocitos", que al cabo son unidos: pues bien, en la memoria aparecen todos los trocitos... e incluso el resultado final: el número de serie correcto para cualquier clave de usuario introducida. Última edición por dec fecha: 28-03-2007 a las 18:17:37. |
|
|
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 |
|