Copy Link
Add to Bookmark
Report

SET 020 0x0c

  

-[ 0x0C ]--------------------------------------------------------------------
-[ CRACKING BAJO LINUX - IV ]------------------------------------------------
-[ by SiuL+Hacky ]----------------------------------------------------SET-20-


1. PROTECCIONES COMERCIALES -------------------------------------------

Vamos a tener en esta entrega una mezcla de teoria y practica, donde por
un lado conoceremos detalles de una proteccion comercial bastante
extendida en el mundo linux/unix; y por otro aplicaremos conceptos
generales que si observais con cuidado se suelen repetir con frecuencia
en este tipo de protecciones.

Afortunada o desafortunadamente linux esta todavia bastante libre de
aplicaciones comerciales, o al menos de aquellas que no permiten
mediante una licencia especial su uso gratuito (tal como al final han
hecho WordPerfect, StarDivision y otra gente). Por ello tampoco es de
esperar un desarrollo de soluciones de tipo comercial para proteger
programas. Incluso en Windows donde la explosion de software comercial
es tremenda, el hecho de licenciar un sistema de proteccion/gestion de
licencias es minoritario y predominan sistemas mas o menos caseros (y
mas o menos eficaces) de proteccion).

Un ejemplo claro de protecciones comerciales en Windows serian la
populares mochilas o llaves hardware. Haciendo un inciso, hay que
señalar que un uso adecuado de una mochila, debe hacer un programa
practicamente seguro, a no ser de que se disponga de una de ellas y se
pueda hacer un estudio para su emulacion. Bueno, pues a pesar de esto,
una gran parte de ellos son crackeables de forma sencilla.

Uno de los problemas fundamentales en el uso de soluciones comerciales:
la desatencion hacia la proteccion es tal, que no solo no se invierte el
menor medio humano (que no economico) en desarrollar la proteccion, sino
que la forma de "empalmar" la proteccion al resto del programa, lo suele
hacer altamente vulnerable. De alguna forma es de esperar que si uno
paga por un sistema de proteccion, no tenga que perder un segundo en
adaptar el programa.

Es aqui donde llegamos a esos chicos tan raros que programan
aplicaciones en unix, generalmente sobre cosas tan esotericas como
simulaciones quimicas, estudio geofisicos, etc ... El panorama hasta
ahora es muy poco ingenioso. Este tipo de aplicaciones cuestan muchisimo
dinero, y como generalmente su ambito de uso es muy reducido, tampoco
les debe importar demasiado que no se proteja. Eso no significa que lo
dejen en plan "copien y disfruten"; por el contrario compran un
programa/conjunto de utilidades que venden los chicos de Globetrotter
Software, y que casi todo el mundo que trabaja con estaciones de trabajo
habra oido alguna vez: Flexlm. Si, flexlm (Flex License Manager) parece
ser la forma mas generica de proteger, bien sea un compilador de Sun,
una aplicacion para SGI, u otras aplicaciones que ultimamente se han
dignado a portar a linux. Por cierto, me cuentan por ahi, que hay
aplicaciones de NT (New Testament) que tambien lo usan.

Para el que no lo conozca, estos chicos de Globetrotter Software han
hecho un autentico negocio. Su lista de clientes es importante, y la
cantidad de bazofia comercial que podeis encontrar en su web
(www.globetrotter.com) es tremenda. Vamos que saben vender bien la moto
esta gente. Esto en web, por lo que supongo que una presentacion en
directo de sus productos debe ser como para perder el control. Si esto
lo mezclais con licencias, patentes y todo eso, da la impresion de que
lo que estas comprando es algo asi como el Gate-keeper que salia en "La
Red"
. Ya juzgareis vosotros mismos, pero a mi me parece que, en general,
es el timo de la estampita aun sin conocer lo que cuesta. Y digo en
general, porque puede ser un buen esquema, siempre que no se implemente
por cuenta propia algunas funciones que permite FlexLM. Pero entonces,
estamos pagando por algo que no protege, lo que protege es la parte
generada por el comprador.



2 . FlexLM. Cuestiones generales -------------------------------------

Ya esta bien de hablar vaguedades. ¿ que es y como funciona FlexLM ?
Hay dos modos principales de funcionamiento:

1) En el primero de ellos hay una especie de esquema cliente/servidor.
El cliente estaria integrado dentro del programa a proteger, y el
servidor seria un programilla o demonio generado via flexlm (y donde
cada empresa puede introducir variantes y mejoras). En este modo aparece
la utilidad "lmgrd" que hace las veces de inetd y se encarga de lanzar
diversos demonios. Cada demonio perteneceria a una empresa/producto y
obviamente se encargarian independientemente de dar acceso a los
clientes. Cada demonio lee la informacion de un fichero de licencia con
un formato estandard que genericamente (hay peque~as variaciones)
incluye: nombre del programa a proteger, numero de licencias, fecha de
caducidad y un hash que verifica los contenidos anteriores.

2) En el otro, el cliente lee directamente el fichero de licencia.

Si nos ponemos la camiseta de Globetrotter, diriamos que con la primera
de las opciones, es posible tener licencias flotantes, es decir n
licencias a usar por n ordenadores, pero sin fijar cuales. Bueno, blah,
blah. La cuestion es ¿ como de seguro es FlexLM ? Lo que opina
Globetrotter de la la vulnerabilidad de su producto es (traducido):

*** ATAQUE SENCILLO ***
Ejecutando la aplicacion sobre un depurador si esta conserva informacion de
depurado (unstripped para ser tecnicos).

=> es cierto. Es una ataque sencillisimo, y es el gran problema de todo el
producto: al final todo se reduce a:

llamar funcion_check_supercomplicada
es correcta la licencia ?

y esta decision suele ser sencilla de localizar (vistosos mensajes de
error) y mas facil todavia de parchear. Otro inciso, no hace falta que
haya informacion de simbolos para crackear un programa asi. Si esta
informacion existe, lo que facilita es que se reviente completamente
(como veremos) el sistema FlexLM.

*** ATAQUE DIFICIL, DEPENDIENTE DE LA CONFIGURACION ***
"Matando los demonios. Si, a pesar de todo, no se usa uno de los
temporizadores incorporados, y no se llama a la funcion HEARTBEAT(),
entonces la proteccion software puede ser puenteada por alguien que mate
los demonios, ya que las aplicaciones nunca detectarian que el demonio
esta caido."


=> de dificil nada. Debe estar en el grupo de los faciles, ya que la funcion
heartbeat puede ser parcheada y se acabo el invento. O mejor se parchea todo
;)


*** ATAQUE MUY DIFICIL *** (...suena bien eh ?)
"Adivinando los hash que pertenecen al fichero de licencia.[...] The
algorithm used is a proprietary one-way block chaining encypherment of
all the input data"
.

=> me niego a traducir esta obra de arte. Por lo demas, el hash tiene 48
bits. sigamos

"Escribiendo un nuevo demonio que emule el original. FlexLM encripta el
trafico entre el cliente y el demonio para hacer mas dificil este tipo
de ataques"
.

=> en cuanto a ingenieria inversa me parece con diferencia el tema mas
interesante, aunque las debilidades anteriores ya desacreditan el sistema.

"Ejecutando el depurador en un ejectuble sin simbolos de depurado. Esto
requiere que alguien encuentre la llamadas-FlexLM sin ningun
conocimiento en la tabla de simbolos"
.

=> guau, o sea que vamos a utilizar el ataque muy dificil. Pero que
buenos que somos.



3 . Funcionamiento interno de FlexLM ---------------------------------

Bueno hasta aqui mucho de blah, blah, blah, propaganda, marketing y esas
cosas. Ahora bien, las bases sobres la que se asienta son solidas ?

Para ello, lo mejor es irse al web de Globetrotter (www.flexlm.com creo
que tambien valia) y pillar el kit de desarrolladores. Hace ya unos
cuantos meses pille el de la version 6.1, que es el que incorporan la
mayoria de los programas (si, flexlm se actualiza, ya se sabe hay que
sacar nuevas versiones cueste lo que cueste). Este kit es una autentica
mina de oro, ya que facilita aparte de una documentacion bastante
completa (hay, logicamente funciones interesantes no documentadas), los
siguientes elementos:

1. Gestor de licencias (lmgrd)
2. Codigo fuente de un ejemplo demonio-cliente
3. Utilidades para generacion de licencias
4. Tres librerias que contienen todo el API de FlexLM

Dentro del 3er punto esta incluida una utilidad llamada lmcrypt. Esto,
lo creais o no, es una generador de licencias. Esto es un nuevo
concepto, resulta que la empresa que vende la proteccion facilita un
generador de licencias. Ya no es necesario crearte tu propia programa
que destripe las entrañas del algoritmo de generacion, no, te lo dan
ellos.

Hombre, hay que matizarlo, pero es asi como vereis. Bueno nos habiamos
bajado el kit de desarrollo. Este viene pseudoencriptado, con lo cual es
preciso perder unos segundos (pocos eso si) en sacar la clave. No voy a
entrar en mucho detalle, ya que creo que es justo que si alguien quiere
acceder a este material se lo trabaje un poco. De todas formas, es muy
sencillo y utilizando ltrace se consiguen las pistas para sacar la clave
facilmente.

Aun asi si alguien no es lo suficientemente capaz, siempre puede
arrastrarse a los chicos de Globetrotter y que te manden la clave (que
es lo que supuestamente todo el mundo deberia hacer).

Es facil al principio perderse entre la documentacion, por lo cual, os
voy a resumir en que se basa el sistema. Hay 7 elementos clave para cada
demonio comercial (entendiendo por demonio comercial, todo el sistema de
gestion de licencias utilizado para un programa determinado ... que hay
mucho mal pensado):

* 2 semillas de encriptacion exclusivas.
* 5 claves de 32 bits.

Para la generacion de los hash que autentifican las licencias, son
fundamentales estas dos semillas, ya que conociendolas es posible
autentificar tantas licencias como uno quiera. Las cinco claves son
utiles para poder instalar el kit y para generar un demonio. Estos
datos, son logicamente utilizados por las funciones del API, por lo que
se empaquetan en la siguiente estructura de datos:

typedef struct {
short tipo;
unsigned long semillas[2];
unsigned long claves[4];
short flexlm_version;
short flexlm_revision;
char flexlm_patch[2];
char behavior_ver[LM_MAX_BEH_VER + 1];
} codigos;

Supongamos que hemos comprado la cosa esta y nos han pasado las 2
semillas y las 5 claves. El programa de instalacion del kit nos pide
todos estos datos, y nos genera un cliente, un demonio y otras cosas
(ya, ya se que no teneis ninguno de estos datos, pero estamos hablando
en un caso generico). Hay una utilidad llamada lmcrypt, que recibe como
entrada una licencia en la que el hash esta a cero, y nos devuelve el
fichero de licencia con el hash adecuado. La forma en que genera el
hash, es mediante esta funcion:

int lc_cryptstr(job, STR, STR_RETURN, *CODIGOS, flag, filename, errors)

Esta funcion esta documentada en los manuales, y os he puesto en
mayusculas los parametros importantes:

STR: recibe la cadena de texto donde se especifica sobre que programa se
aplica la licencia, si caduca y cuando, y el numero de licencias
permitidas. Uno de los campos es el hash de autenticacion, y que en
este caso se pone a cero. Por ejemplo:

"FEATURE word MSOffice 1.0 permanent 4 0"

CODIGOS: es una estructura como la de arriba, con las semillas y las claves,
que puestamente se usaran para crear el hash

STR_RETURN: devuelve una cadena de texto equivalente a STR, pero donde el
hash ya no es cero, sino son los 48 bits correspondientes.

Vale, la licencia esta generada. ¿Porque no la genera cualquiera ?
Hombre, pues porque hacen falta esos 7 datos ? ¿7 datos ? bueno, en
realidad solo son 6, ya que en la estructura CODIGOS solo aparecen 4
claves (ya veremos que pasa con la quinta).



4 . Debilidades del sistema ------------------------------------------

Ahora resulta que el usuario Pepito se ha comprado su programa carisimo, y
le han dado un fichero de licencia que podria ser asi:

SERVER localhost.localdomain ANY
VENDOR khoral /usr/local/flexlm/v6.0/i86_l1/khoral
FEATURE xprismpro khoral 1.0 permanent 4 XXXXXXXXXXXX

las XXX son el hash eh !! Arrancara el gestor de licencias (lmgrd) que
ira a buscar ese fichero y tendra que comprobar el hash. Bien, por
sentido comun, y aunque uno no sepa nada de cracking, o el sistema es
muy bueno o de alguna forma para comprobarlo hay que generarlo otra vez
y comparar.

¿ Como comprueba el hash el demonio ? Tomando el demonio de ejemplo que
viene en el kit (y al igual que hacen la mayoria de los demonios
comerciales que circulan) primero se incializa el sistema llamando a la
funcion lc_init:

lc_init(--, --, CODIGOS*, --)

Je, je, luego efectivamente en el demonio hay una copia de la estructura
CODIGOS, con la semillas y las 4 claves. QUE FRAUDE ! pensareis. Aqui es
donde FlexLM dice: Ah, pero la seguridad esta garantizada ya que las
semillas estan encriptadas (xoreadas) con la clave numero 5 que no esta
incluida en el demonio (y asi es efectivamente). Esta funcion de
inicializacion recibe las 4 claves y las dos semillas xoreadas con la
clave numero 5.

Recapacitemos, nos dicen que NO estan en el demonio todos lo elementos
que nos permitirian generar licencias. Yo, desde luego, no crei que
comprobaran el hash sin recurrir a los datos originales con el que fue
generado, luego la clave numero 5 debian generarla de alguna forma al
vuelo (o bien estaba "escondida" en el demonio). Si analizamos mas
detenidamente el codigo del demonio de ejemplo, vemos que la
comprobacion del hash se hace con una llamada a la funcion lc_crypt, que
obviamente no esta documentada

lc_crypt (--, --, --, CODIGOS*)

pero en la que la estructura codigos recibe ya las semillas originales
(desxoreadas). Je, je, luego han generado la clave numero 5.

En definitiva y ahorrandonos listados en ensamblador (ya llegaran) , la
clave numero 5 se genera mediante una llamada a la funcion, tambien
indocumentada l_svk (secret vendor key ?)

int l_svk(char*,CODIGOS*)

el parametro de entrada (y co-responsable de su generacion) es nada mas
y nada menos que el nombre del demonio :D. Ciertamente curioso. Esta
funcion l_svk esta disponible en las librerias del kit de desarrollo,
luego podemos hacernos un programita en el que rellenando los datos
correspondientes a las semillas xoreadas y las 4 claves, nos facilite la
clave numero 5, y lo que es mas importante las semillas originales con
las que generar licencias en serie.

Resumiendo, en el codigo del demonio (y en su nombre) estan los datos
para generar todas las licencias del mundo. El unico problema es
identificar la llamada a la funcion lc_init, por ejemplo, en la que se
pasa como parametro una estructura de tipo CODIGOS. Pero eso no es un
gran problema una vez que sabemos como es (en el demonio del kit de
desarrollo, si que hay tabla de simbolos y es inmediato localizar la
funcion en el listado en ensamblador).

Mi opinion es que si se dispone de un fichero de licencia operativo
(sabiendo asi las sintaxis de cada campo), es bastante sencillo generear
licencias adicionales o modificar las existentes. En el resto de los
casos se complica algo.



5 . Ficheros de licencias. Ejemplo practico ---------------------------

Despues de esta introduccion general a lo que es FlexLM, que no pretende
ser demasiado exhaustiva por cuestiones de espacio (si acaso en otras
entregas, trataremos un caso concreto de FlexLM que sea especialmente
didactico), vamos a ver un ejemplo practico que si bien esta flexlm
metido por medio, no es exactamente flexlm.

El programa se llama IDL 5.2, y significa algo asi como Interactive Data
Language. Es una especie de lenguaje de programacion muy orientado a la
presentacion/visualizacion grafica de datos, y que segun cuenta la gente
es bastante potente. Lo podeis encontrar en el web de rsi:

www.rsinc.com

Tienen una demo muy curiosa. Supuestamente es completamente funcional si
exceptuamos salvar datos e imprimir. Eso si solo durante 7 minutos,
transcurridos los cuales te echa sin el menor miramiento. Vereis que
cada vez afinan mas. Existe la posibilidad de que te den una licencia
temporal para evaluarlo (gratuita), y luego si lo compras, la licencia
va por FlexLM.

Curiosamente la forma de obtener una licencia temporal de evaluacion, no
es con FlexLM. No se muy bien, si es que no se fian del sistema (en cuyo
caso parece deberian cambiarlo), o bien no quieren pagar mas a los
chicos de Globetrotter. Se han hecho su propio programita que genera un
fichero de licencia que desde luego no esta en modo texto.

Este programa, llamado genver, genera un numero aleatorio que tu le
comentas al comercial de turno por telefono, y este te genera otro
numero que introduces al programa para que genere la licencia.

Hay claramente tres opciones:

1) Evitar que caduque a los 7 minutos (hay una bonita ventana que nos
comunica que el tiempo se ha acabo).

2) Generar una licencia temporal.

3) Generar un licencia Flex.

Vamos a descartar la primera y tercera opcion. La primera porque el
programa esta hecho en Motif, y no conocemos nada sobre ello, ni sobre
Toolkits, mensajes, widgets ni nada de eso. Ademas el programa es
gigantesco y los listado en ensamblador son enormes (de mas de 60 Mb).
Hasta ahora no hemos tocado nada sobre Motif, ya que algo me dice que
esta cayendo en deshuso y es en general bastante farragoso (esta basado
en objetos, es decir, codigo gigantesco). La tercera es por una cuestion
preventiva, ya que ya me ha ocurrido varias veces de estar mucho tiempo
forzando funcionalidades que luego no estaban disponibles en el cliente,
con lo cual manipular licencias sin tener una referencia de que el
cliente las va a saber manejar, puede ser una perdida de tiempo. En
cualquier caso, con lo expuesto aqui podreis obtener facilmente tanto
las semillas como la 5 claves (el que lo consiga que me las mande, y
tendra soporte on-line de flexlm. A ver si os animais).

Manos a la obra, ejecutamos el programa genver (que se encuentra en el
directorio idl/bin/bin.linux/genver) y nos dice:

Your number for today is: 6239

Enter length of trial period in days :

si le ponemos que 1 millon, nos echara rapidamente, pero si ponemos algo
razonable como 100, nos respodera:

Enter RSI supplied installation key:

esta es la que supuestamente nos dan por telefono. Respondiendo lo que
sea, nos dice que es invalida. Ejectando el maravilloso programa ltrace
que hemos descrito ampliamente en entregas anteriores, obtenemos este
interesante listado:

[080490e2] fopen("./idl.genver", "w") = 0x0804b028
[08049122] chmod("./idl.genver", 0666) = 0
[080493ca] ftime(0xbfffe5dc, 0, 0x40005ff0, 0x08048940, 0xbfffe5dc) = 0
[0804946b] printf("\nYour number for today is: %lu\n"..., 14098) = 34
[08048e24] fileno(0x0804afc8) = 0
[08048e2f] isatty(0) = 1
[08048e4a] printf("Enter %s: ", "length of trial period in days ") = 39
[08048e68] fgets("100\n", 1024, 0x0804afc8) = 0xbfffe164
[08048f1c] sscanf("100\n", "%ld", -1073749672, -1073749672) = 1
[08048f54] sscanf("100\n", "%ld", -1073749672, -1073749672) = 1
[08048e24] fileno(0x0804afc8) = 0
[08048e2f] isatty(0) = 1
[08048e4a] printf("Enter %s: ", "RSI supplied installation key") = 37
[08048e68] fgets("235253453536346"..., 1024, 0x0804afc8) =0xbfffe164
[08048f1c] sscanf("235253453536346"..., "%ld", -1073749672,-1073749672) = 1
[08048f54] sscanf("235253453536346"..., "%ld", -1073749672,-1073749672) = 1
[08048db1] fprintf(0x0804af70, "genver: %s\n\n", "invalid key") = 21
[08048dde] exit(1) = <void>

hay dos secuencias muy parecidas, una la que lee el numero de dias, y
otra la que lee la llave. La secuencia es printf -> fgets -> sscanf ->
sscanf. Si os fijais en el puntero de programa, la localizacion de estas
funciones es la misma, es decir, hay una especie de funcion que hace las
labores de "imprime cartel, lee caracteres, pasalo a numero". No parece
muy sensato que la funcion sscanf (que es similar a scanf) se llame dos
veces con los mismos argumentos, pero ...

Generemos un listado en ensamblador (con el script dasm, cuya ultima
actualizacion acompa~o al final. Por cierto disculpad que los mensajes
esten en ingles) del programa genver, y examinemos las proximidades de
la secuecia fgets -> sscanf:

Reference to function : fgets

0x08048e63 call 0x08048798
0x08048e68 addl $0xc,%esp
0x08048e6b movl %eax,%eax
0x08048e6d movl %eax,0xfffffbf8(%ebp)
0x08048e73 cmpl $0x0,0xfffffbf8(%ebp)
0x08048e7a jne 0x08048e90

fgets devuelve en eax el puntero a la cadena leida, luego esta
comprobando que se ha leido algo. Posteriormente comprueba que no es
ningun caracter exotico (CR, tabulador, ...), y hace una llamada (dos
veces, solo os pongo la segunda) a sscanf:

int sscanf( const char *cadena, const char *formato, &numero)


0x08048f38 leal 0xfffffbf0(%ebp),%eax
0x08048f3e pushl %eax; <---- salva el puntero al numero
0x08048f3f leal 0xffffeb17(%ebx),%edx
0x08048f45 movl %edx,%eax
0x08048f47 pushl %eax <---- salva el punt. a la cadena de formato
0x08048f48 movl 0xfffffbf8(%ebp),%eax
0x08048f4e pushl %eax <---- salva la cadena origen

Reference to function : sscanf
<---- sscanf devuelve en eax la cantidad
<---- de caracteres convertidos

0x08048f4f call 0x08048848
0x08048f54 addl $0xc,%esp
0x08048f57 movl %eax,%eax
0x08048f59 cmpl $0x1,%eax <---- comprueba que se ha convertido un car.
0x08048f5c je 0x08048f92 <---- salta si es cierto
0x08048f5e leal 0xfffffbfc(%ebp),%eax
0x08048f64 pushl %eax

[...]

0x08048f8a call 0x08048d80
0x08048f8f addl $0x8,%esp

Referenced from jump at 08048f5c ;

0x08048f92 movl 0xfffffbf0(%ebp),%eax <--- mueve el numero devuelto por
<--- sscanf a eax
0x08048f98 jmp 0x08048fa0
0x08048f9a leal 0x0(%esi),%esi

Referenced from jump at 08048e7e ; 08048f98 ;


0x08048fa0 movl 0xfffffbec(%ebp),%ebx
0x08048fa6 movl %ebp,%esp
0x08048fa8 popl %ebp
0x08048fa9 ret

luego toda esta funcion, lo que hace es devolver en eax la llave
introducida por el usuario. Para averiguar a donde retorna esta funcion,
lo mejor es ejecutar el programa en el depurador y al encontrarnos en
este punto del programa (tras introducir la llave, ya que esta parte de
codigo tambien se ejecuta cuando introducimos el numero de dias),
ejecutar el comando gdb llamado "back", que devuelve el arbol de
llamadas en ese punto:

#0 0x8048f1c in strlen ()
#1 0xbfffe38c in ?? ()
#2 0x80495a6 in strlen ()
#3 0x804899b in strlen ()

luego venimos del codigo con direccion 0x80495a6. Examinemoslo:

0x080495a1 call 0x08048e00 <--- esta es la funcion que hemos visto
<--- y que devuelve la llave leida
0x080495a6 addl $0x4,%esp
0x080495a9 movl %eax,0xffffeaf4(%ebp)
0x080495af movl 0xffffeaf4(%ebp),%edi
0x080495b5 movl %edi,0xffffeb4c(%ebp)
0x080495bb movl 0xffffeb4c(%ebp),%eax
0x080495c1 movl %eax,0xffffeaf4(%ebp)
0x080495c7 movl 0xffffeaf4(%ebp),%edi
0x080495cd cmpl %edi,0xffffeb48(%ebp)

nunca habia visto algo tan ineficiente, estas lineas solo valen para que
finalmente se compare el numero introducido con el contenido en
ebp+0xffffeb48, que es un numero que cambia cada vez, y que para vuestra
informacion es la clave correcta. Pongo el resto del codigo.

0x080495d5 pushl $0x1 <--- esto se ejecuta si la clave es erronea
0x080495d7 leal 0xffffeee2(%ebx),%edx
0x080495dd movl %edx,0xffffeaf4(%ebp)
0x080495e3 movl 0xffffeaf4(%ebp),%eax
0x080495e9 pushl %eax
0x080495ea call 0x08048d80 <--- aqui se llamara al printf con el
<--- mensaje de llave invalida

Ya sabemos donde esta la llave buena, ahora os voy a ense~ar una forma
sencilla de que nos aparezca mientras se ejecuta el programa. Para ello
sabemos que cuando nos solicita la clave, el programa ya la ha generado
internamente, y la idea es usar el printf donde nos la solicita para
mostrar ese numero en claro. Vuelvo a poner la forma del printf donde se
solicita introducir la llave:

printf("Enter %s: ", "RSI supplied installation key")

que os parece si lo cambiamos a:

printf ("Enter %x: ", puntero_a_la_llave_que_el_ha_calculado);

Para cambiar la cadena de formato, no hay mas que editar el fichero
binario (sigo sugiriendo dosemu+hiew) y cambiar la "s" por la "x". Y por
ultimo habra que cambiar el puntero a "RSI ..." por un puntero a la
llave. Para esto ultimo si ejecutamos genver bajo un depurador y
detenemos el programa en la instruccion 0x080495a9 (ver listado de
arriba), podemos averiguar la direccion absoluta de la llave, es decir
cuanto vale ebp+0xffffeb48 en ese punto. Se apunta, llamemosla
direccion_llave.

Volviendo al printf que vamos a modificar, esta es su estructura:

0x08048e38 movl 0x8(%ebp),%eax
0x08048e3b pushl %eax <--- salvar "RSI ..."
0x08048e3c leal 0xffffeb0c(%ebx),%edx
0x08048e42 movl %edx,%eax
0x08048e44 pushl %eax <--- salvar "Enter %s"

Reference to function : printf

0x08048e45 call 0x08048778

si en este punto vemos el valor de ebp, veremos que solo se diferencia en
0x6c unidades de la direccion_llave, es decir modificando:

0x08048e38 movl 0x8(%ebp),%eax
por
0x08048e38 movl 0x6c(%ebp),%eax

apuntara a la llave correcta, que nos aparecera claramente, es decir, en vez
de preguntar:

Enter RSI supplied installation key:

preguntara

Enter llave_correcta:

elegante no ;-) ? Como daño colateral, en vez de solicitarnos el numero de
dias tambien aparecera un numero, pero bueno, creo merece la pena el cambio.

Hasta la proxima entrega,

SiuL+Hacky
si_ha@iname.com

------------------------------ listado de dasm ------------------------

#!/usr/bin/perl
;############ MODIFY THIS LINE WITH YOUR PERL LOCATION ############
push(@INC,"/usr/lib/perl5");
require("flush.pl");


;##################################################################
;######## LINUX DISASSEMBLER 2.0799
;######## (C) SiuL+Hacky Jul 1999
;######## You may copy, modify, distribute this program and
;######## is up you to keep this header here
;######## Usage: dasm exe_file dasm_file
;##################################################################


$f_input=$ARGV[0];
$f_output=$ARGV[1];
&printflush(STDOUT, "\nCreating disassembled file ...");
$return=system("objdump -d -T -x --prefix-addresses ".$f_input.">".$f_output."2");
if ($return!=0){
print "\nERROR OPENING OBJDUMP $return";
print "\nUsage: dasm exe_file dasm_file";
print "\nBe sure to get objdump in your path. Check also file permissions\n";
exit(1);
}

open(INPUT, "<".$f_output."2");

&printflush(STDOUT, "\nReading strings ...");
$_=<INPUT>;
while (!/.rodata/){
$_=<INPUT>;
}
($rubbish, $rest)=split(/.rodata/,$_,2);
($rubbish, $rest)=split(/0/,$rest,2);
@numbers=split(/ /,$rest,5);
$size=hex($numbers[0]);
$starting_address=hex($numbers[1]);
$end_address=$starting_address+$size;
$offset=hex($numbers[3]);
open(CODIGO, "<".$f_input);
seek(CODIGO,$offset,0);
read(CODIGO,$cadena,$size);
close(CODIGO);


SEARCH: while (<INPUT>){
last SEARCH if (/SYMBOL TABLE/);
}
if (/SYMBOL TABLE/){
&printflush(STDOUT, "\nProcessing symbol table ...");
$_=<INPUT>;
while (!/^\n/){
@st_element=split(/ /, $_);
$_=$st_element[$#st_element];
chop;
$symbol_table{$st_element[0]}=$_;
$_=<INPUT>;
}
}
else {
seek(INPUT,0,0);
}

while (!/\.text/){
$_=<INPUT>;
}
&printflush(STDOUT, "\nProcessing jmps and calls ...");

######### the regex gets rid of possible line information #############


while (<INPUT>){
$_=~ s/0x//g;
$_=~ s/<.*?>//g;
$_=~s/ / /g;
if (/j/){
($direccion,$inst,$destino)=split(/ /,$_,3);
$destino=~s/ //g;
chomp($destino);
$salto{$destino}.=($direccion." \; ");
}
elsif (/call/){
($direccion,$inst,$destino)=split(/ /,$_,3);
$destino=~s/ //g;
chomp($destino);
$call{$destino}.=($direccion." \; ");
}
}

seek(INPUT,0,0);
&printflush(STDOUT, "\nWritting references ...\n");
open(OUTPUT, ">".$f_output) || die print "\nError opening write file\n";
print OUTPUT "FILE REFERENCED\n\n";

while (!/Disassembly of section .text:/){
$_=<INPUT>;
print OUTPUT;
}
$char=".";
$counter=0;
while(<INPUT>){
$counter++;
if ( ($counter % 400)==0){
printflush(STDOUT,$char);
if ( ($counter % 4000)==0){
printflush(STDOUT,"\r");
if ($char eq "."){ $char=" ";}
else { $char=".";}
}
}
$copia=$_;
$_=~s/0x//g;
$_=~s/<.*?>//ge;
$_=~s/ / /g;
($direccion, $inst, $destino)=split(/ /,$_,3);
if ( defined( $symbol_table{$direccion} )){
print OUTPUT "\n";
print OUTPUT "---- Function : ".$symbol_table{$direccion}." ----\n";
}
if (/call/){
$destino=~s/ //g;
chomp($destino);
if ( defined( $symbol_table{$destino} )){
print OUTPUT "\n";
print OUTPUT "Reference to function : ".$symbol_table{$destino}."\n\n";
}
}
if ( defined( $salto{$direccion} )){
print OUTPUT "\n";
print OUTPUT "Referenced from jump at ".$salto{$direccion}."\n\n";
}
if ( defined( $call{$direccion} )){
print OUTPUT "\n";
print OUTPUT "Referenced from call at ".$call{$direccion}."\n\n";
}
if (/\$/){
($instruccion, $operand)=split(/\$/,$_,2);
if (!/push/){
($operand, $rest)=split(/\,/,$operand,2);
}
chomp($operand);
$offset=hex($operand);
if ( ($offset <= $end_address) && ($offset >= $starting_address ) ){
$auxiliar=substr($cadena, $offset-$starting_address);
$length=index($auxiliar, pack("x") );
$auxiliar=substr($auxiliar, 0, $length);
$auxiliar=~s/\n//g;
print OUTPUT "\n";
print OUTPUT "Possible reference to string:";
print OUTPUT "\n\"$auxiliar\"\n\n"
}
}
print OUTPUT $copia;
}
close(INPUT);
close(OUTPUT);
print "\n";
system("rm ".$f_output."2");



← previous
next →
loading
sending ...
New to Neperos ? Sign Up for free
download Neperos App from Google Play
install Neperos as PWA

Let's discover also

Recent Articles

Recent Comments

Neperos cookies
This website uses cookies to store your preferences and improve the service. Cookies authorization will allow me and / or my partners to process personal data such as browsing behaviour.

By pressing OK you agree to the Terms of Service and acknowledge the Privacy Policy

By pressing REJECT you will be able to continue to use Neperos (like read articles or write comments) but some important cookies will not be set. This may affect certain features and functions of the platform.
OK
REJECT