Pregunta sencilla de ingeniería inversa - ¿Quién me da un consejo?

Iniciado por morpheus1000, 23 Julio 2016, 01:02 AM

0 Miembros y 1 Visitante están viendo este tema.

morpheus1000

Hola compañeros!, para mí es un gusto saludar una comunidad con tantos aportes como esta.  :rolleyes:

Ahora bien al  grano...

He instalado un software que como medida de seguridad implementa validación de licencias mediante firma digital de la siguiente manera:

El programa constantemente realiza consultas a la base de datos que se instala junto con la distribución de dicho software, específicamente en la tabla "license" de dicha base de datos, este procedimiento VALIDA que nuestro software no esté toqueteado, y lo hace de la siguiente manera:

licensed_users   int(11)
license_id   char(36)
customer_id   char(100)
description   varchar(100)
email   char(100)
bo_type   varchar(64)

En los campos anteriores pertenecientes a la tabla "license" se captura información en el siguiente orden:

1.   Número de licencias a adquirir, por ejemplo yo adquiero 100, de ahí que el campo sea del tipo int(11)
2.   Identificador de licencias, es del tipo char(36)
3.   Identificador de cliente, es del tipo char(100)
4.   Descripcion, es del tipo varchar(100)
5.   Email, es del tipo char(100)
6.   bo_type, es del tipo varchar(64)

He aquí la parte interesante!!..!!..

El programa implementa una función, la cual utiliza TODAS las variables anteriores (campos) para aplicar un algoritmo (probablemente un algoritmo RSA) para obtener una firma y de esa manera VALIDAR, tanto el número de licencias (la parte más importante) como el resto de los datos, que para propósitos prácticos, son irrelevantes.

El resultado se almacena en el campo:

signature, y es del tipo varchar(172)

He estado revisando la base de datos que auto instala el software, y las llaves que se incluyen como ejemplo tienen una longitud exactamente de 172 caracteres:

algo más o menos así:

wxzqVSqFCC7QLjtLwBbXGYY6K77v37bZOW2HMfSCdmwh/qoFyFCvWwxzqVSqFCC7QLjtLwBk1fy3/jkO/bIEDDQxkLNtm5VRoBEWKkEJN0jRdGv3wxzqVSqFCC7QLjtLwBDe76hcuLE1hUetUhRK75JWwxzqVSqFCC7QLjtLwBg=

Me llama la atención que las firmas de ejemplo terminen en signo de igualdad, tuve la oportunidad de ver trabajando una llave genuina en mi lugar de trabajo, y su terminación es en signo de igualdad también...  ;D

La consulta que les hago es:  :huh: :huh: :huh:

¿Qué procedimiento o algoritmo podría yo usar para hacer pruebas con los datos de ejemplo que incluye el programa, esto, con la intención de conocer el procedimiento que los creadores del software usaron para implementar seguridad en el mismo. Y hacer mis propias llaves de prueba. Repito, se usan 6 elementos que combinados dan como resultado la llave de caracteres de 172 caracteres de longitud y terminada en signo de igualdad.  :o

La ingeniería del software es muy útil e interesante y si alguien pudiera ayudarme con alguna sugerencia de que algoritmo poder implementar, se lo agradecería demasiado.

Mis mejores deseos a todos en el foro.,
Gracias de antemano.

MCKSys Argentina

Hola!

La "clave" que has colocado es información encodeada en base 64. Al desencodearla queda información binaria (osea, no es texto plano), la cual debe representar el hash/key/serial que calcula el programa en base a los datos de la base.

Lo que debes hacer es encontrar y analizar la rutina que verifica dichos datos y genera dicha "clave". Una vez analizada la función, podrás generar el proceso inverso, para poder generar las claves que quieras en base a los datos que desees.

Por supuesto, si no tienes idea del tema, vas a necesitar aprender a caminar antes de correr. El FAQ del subforo (link en mi firma) contiene lo necesario para iniciarte en este mundo.

Saludos!
MCKSys Argentina

"Si piensas que algo está bien sólo porque todo el mundo lo cree, no estás pensando."


morpheus1000

Cita de: MCKSys Argentina en 23 Julio 2016, 01:23 AM
Hola!

La "clave" que has colocado es información encodeada en base 64. Al desencodearla queda información binaria (osea, no es texto plano), la cual debe representar el hash/key/serial que calcula el programa en base a los datos de la base.

Lo que debes hacer es encontrar y analizar la rutina que verifica dichos datos y genera dicha "clave". Una vez analizada la función, podrás generar el proceso inverso, para poder generar las claves que quieras en base a los datos que desees.

Por supuesto, si no tienes idea del tema, vas a necesitar aprender a caminar antes de correr. El FAQ del subforo (link en mi firma) contiene lo necesario para iniciarte en este mundo.

Saludos!


Hola, buenos días  :D

Ampliando un poco la información del software en el que estoy trabajando:

Les cuento, la primera vez que vi la el campo SIGNATURE, en la columna de la tabla LICENSE (esa base de datos es fundamental para el programa) inmediatamente me di cuenta que probablemente no estría muy protegido el sistema QUE GENERA dicha SIGNATURE.  :rolleyes: :rolleyes:

A mi ver, la SIGNATURE se genera de la siguiente manera:



Como les comentaba en la entrada anterior, no importa que información esté yo capturando en las variables: dato1, dato2, etc., por ejemplo: nombre: "Juanito Pérez". email: juanito@juanito.com; lo importante es que la SIGNATURE GENERADA corresponda a los datos primarios (valor de las variables) si se usa el proceso CORRECTO que GENERA DICHA SIGNATURE.  ::)

En otras palabras, y para no confundir...

SIEMPRE que se ejecuta el programa, éste lo que hace, es aplicar una función de GENERACIÓN DE SIGNATURE,  usando dato1, dato2, etc, previamente almacenados en la tabla de la base de datos y, COMPARA el resultado con la SIGNATURE guardada en el mismo renglón de la tabla.  :)

Como información adicional, la WebControls.dll, a mi ver, es la librería que realiza LA FUNCION ANTERIORMENTE EJEMPLIFICADA.   :huh:

Y dicha DLL está compilada desde código fuente escrito en C# y se usa como parte del set de Controles de una aplicación web (en este caso corre en un servidor basado en IIS + ASP+DLLs).

La herramienta que estoy usando para visualizar las funciones es:  .NET Reflector y por lo que he visto, no hay implementado código de ofuscación ni de protección, por lo que pienso no ha de ser muy difícil dar con la(s) funcion(es) que estoy buscando.

:huh: :huh:
Necesito una orientación amigos, por que repito, la función que estoy buscando ...concatena ... o ... aplica una operación RSA o HASH o aplica una función personalizada a 6 variables (que ejemplifico en el diagrama que adjunté renglones arriba)y arroja UN único resultado: la SIGNATURE con 172 caracteres de longitud.

Toda ayuda es bienvenida.

Gracias  ;-) ;-)

MCKSys Argentina

Si tienes el código fuente (es lo que te da Reflector), es cuestión de tiempo para que encuentres la función que genera o compara los códigos.

Con un simple análisis ya tendrás la función inversa (o la misma, si termina comparando strings).

Ya casi lo tienes...  :P

Saludos!
MCKSys Argentina

"Si piensas que algo está bien sólo porque todo el mundo lo cree, no estás pensando."


morpheus1000

Buenas tardes

Saludos, y continuando con mi investigación, la SIGNATURE o firma SI es generada mediante algoritmo RSA, y he encontrado 2 datos interesantes:

<Modulo>
vwm4OMJkvRYXYMUUM6c9Diw6oTglMQ291IpIOsHDLW4Ia2xcb9U0cw+qtKfKRavrMO7NjToRvodRnLTlvTlprg6k/bC9/PTKLlul1B+EfE1fCXeE8cD34TD36LpTU+NK4W5eB5G+iTXNl++Y37j96cAb9oquGUWnYBY4s6aSlS8=
</Modulo>

<Exponent>AQAB</Exponent>

Módulo y exponente, estos datos son exclusivos de cada cliente.

:huh: :huh: :huh:

Alguien de ustedes conoce algun generador RSA online al que pueda alimentar con este modulo y exponente para que me genere la FIRMA perteneciente a un cliente en particular, he estado haciendo búsquedas en Google, y aun nada que me sea de utilidad.

Gracias de antemano.

MCKSys Argentina

Cita de: morpheus1000 en 25 Julio 2016, 22:24 PM
Alguien de ustedes conoce algun generador RSA online al que pueda alimentar con este modulo y exponente para que me genere la FIRMA perteneciente a un cliente en particular, he estado haciendo búsquedas en Google, y aun nada que me sea de utilidad.

Revisa ésto.

Saludos!
MCKSys Argentina

"Si piensas que algo está bien sólo porque todo el mundo lo cree, no estás pensando."


morpheus1000

Buenos días y muchas gracias por las respuestas y los ánimos que me dan  MCKSys Argentina, paso a mostrar cierta función, ¿en una chanza me ayudan a revisarla?

A mi entender la función llamada m_AddLicense(string strXml)
Recibe la variable sobre la cual va a trabajar en formato string, y la maneja bajo el nombre de xtrXml:   

private void m_AddLicense(string strXml)
{
    ClientCmd cmd = new ClientCmd(ServerCapabilities.ServiceAddress(), ServerCapabilities.TcpNmeaPort());
    try
    {
        cmd.Connect("TRUST", Session.CurrentSession.User.Username, null);
        cmd.CmdToServer(new AddLicenseCmdBuilder(strXml));
    }
    finally
    {
        cmd.Disconnect();
    }
}


La variable ClientCmd  tomaría el valor devuelto por la función ClientCmd() que a su vez trabaja utilizando los parámetros devueltos por las funciones.

ServerCapabilities.ServiceAddress() y ServerCapabilities.TcpNmeaPort()
La parte que no logro entender bien es el Try donde:

La funcion cmd.Connect() usa la cadena de caracteres "TRUST", y el contenido de la vairable Session.CurrentSession.User.Username, finalmente aplica la palabra null (no entiendo a qué se refiere).

cmd.CmdToServer() Usa "new" y finalmente ejecuta la función AddLicenseCmdBuilder()
Con el string que inicialmente recibió la función principal, ¿Quién de ustedes me puede orientar en este paso?  :huh: :huh: :huh:

Saludos!

MCKSys Argentina

Cita de: morpheus1000 en 27 Julio 2016, 19:50 PM
Buenos días y muchas gracias por las respuestas y los ánimos que me dan  MCKSys Argentina, paso a mostrar cierta función, ¿en una chanza me ayudan a revisarla?

A mi entender la función llamada m_AddLicense(string strXml)
Recibe la variable sobre la cual va a trabajar en formato string, y la maneja bajo el nombre de xtrXml:   

private void m_AddLicense(string strXml)
{
    ClientCmd cmd = new ClientCmd(ServerCapabilities.ServiceAddress(), ServerCapabilities.TcpNmeaPort());
    try
    {
        cmd.Connect("TRUST", Session.CurrentSession.User.Username, null);
        cmd.CmdToServer(new AddLicenseCmdBuilder(strXml));
    }
    finally
    {
        cmd.Disconnect();
    }
}


La variable ClientCmd  tomaría el valor devuelto por la función ClientCmd() que a su vez trabaja utilizando los parámetros devueltos por las funciones.

ServerCapabilities.ServiceAddress() y ServerCapabilities.TcpNmeaPort()
La parte que no logro entender bien es el Try donde:

La funcion cmd.Connect() usa la cadena de caracteres "TRUST", y el contenido de la vairable Session.CurrentSession.User.Username, finalmente aplica la palabra null (no entiendo a qué se refiere).

cmd.CmdToServer() Usa "new" y finalmente ejecuta la función AddLicenseCmdBuilder()
Con el string que inicialmente recibió la función principal, ¿Quién de ustedes me puede orientar en este paso?  :huh: :huh: :huh:

Saludos!

Sin mayor cantidad de codigo no sabria decirte, pero de ese codigo leo:

1) Se asigna a la variable cmd una instancia de la clase ClientCmd. La clase se inicializa (construye) con los parametros que se le pasan.

2) Dentro del try llama al metodo Connect de la clase. Esto debe realizarlo para establecer una conexion con una base de datos o algo parecido. Los parametros son la cadena TRUST, el nombre (aparente) del usuario de la sesion actual y el valor null (para saber que deberia ir en ese 3er parametro, habria que revisar la definicion del metodo).

3) El metodo CmdToServer se encargaria de agregar la licencia, usando como parametro una instancia de la clase AddLicenseCmdBuilder la cual se inicializa (construye) con strXml como parametro.

Saludos!
MCKSys Argentina

"Si piensas que algo está bien sólo porque todo el mundo lo cree, no estás pensando."


morpheus1000

#8
CitarSin mayor cantidad de codigo no sabria decirte, pero de ese codigo leo:

1) Se asigna a la variable cmd una instancia de la clase ClientCmd. La clase se inicializa (construye) con los parametros que se le pasan.

2) Dentro del try llama al metodo Connect de la clase. Esto debe realizarlo para establecer una conexion con una base de datos o algo parecido. Los parametros son la cadena TRUST, el nombre (aparente) del usuario de la sesion actual y el valor null (para saber que deberia ir en ese 3er parametro, habria que revisar la definicion del metodo).

3) El metodo CmdToServer se encargaria de agregar la licencia, usando como parametro una instancia de la clase AddLicenseCmdBuilder la cual se inicializa (construye) con strXml como parametro.

Saludos!

Muchas gracias!

Hace mucho no revisaba sintaxis de un programa C, (en este caso C# que salvo las librerías exclusivas de MS, es la misma cosa).

Y tienes razón, esta función invoca a otras, y aunque el desarrollador original dejo la estructura bastante ordenada, la falta de practica por mi parte, esta haciendo que me lleve algo mas de tiempo, sin embargo ahí estamos.

Gracias otra vez, seguiré revisando el fuente y cualquier novedad la estaré publicando.

Saludos.


Buenos dias

Saludos, ya he empezado a toquetear el ensamblado con reflector + reflexil pero me ha arrojado el siguiene error de compilacion, alguien de ustedes lo conoce??

Descripción: Error durante el procesamiento de un archivo de configuración requerido para dar servicio a esta solicitud. Revise los detalles de error específicos siguientes y modifique el archivo de configuración en consecuencia.

Mensaje de error del analizador: No se puede cargar el archivo o ensamblado 'WebControls' ni una de sus dependencias. La definición del manifiesto del ensamblado no coincide con la referencia al ensamblado. (Excepción de HRESULT: 0x80131040)

Saludos

MOD EDIT: No hacer doble post.