elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.

 

 


Tema destacado: ¿Eres nuevo? ¿Tienes dudas acerca del funcionamiento de la comunidad? Lee las Reglas Generales


  Mostrar Temas
Páginas: [1] 2 3
1  Programación / Programación C/C++ / Recomendacion de libreria para serializar paquetes de red [C++] en: 10 Agosto 2018, 21:52 pm
Estoy haciendo una aplicacion para capturar el trafico de un programa especifico. En realidad no tengo que serializar paquetes de red, sino simplemente los mensajes que se envian a travez de sockets, en otras palabras el buffer del paquete.

Lo que estoy haciendo basicamente es redireccionando las funciones send y recv a unas propias para luego serializar toda la comunicación de la aplicación.

Estuve probando la libreria Protobuf de Google y es muy facil de usar, el problema es que almacena todos los datos en memoria y hay que serializarlos/deserializarlos todos juntos, y basicamente la memoria va aumentando lentamente.

Yo estaria necesitando una libreria que me permita serializar por partes, es decir, ir añadiendo los paquetes al archivo a medida que van llegando.

La salida que espero es mas o menos así, aunque no necesariamente en json, preferiria datos binarios.
Código:
{
     "date": "2018-08-10T17:03:15Z",
     "version": "7.6.1.1",
     "packets":
     [
      {
       "buffer": "xxxxxxxx",
       "date": "2018-08-10T17:18:16Z"
      },
      {
       "buffer": "xxxxxxxx",
       "date": "2018-08-10T17:18:16Z"
      },
      ...
     ]
}

Vi que por ejemplo wireshark usa Cap'n Proto pero no estoy del todo seguro que permita serializar por partes, y mucho menos deserializar solo algunos datos.

Flatbuffers al parecer permite deserializar por partes, pero no estoy seguro si se puede hacer una serialización "por partes" como explique mas arriba.

De cualquier modo, incluso es posible hacer lo que requiero? No se si existe un nombre tecnico para esto, hice una busqueda en google pero no encontre nada. Quizás solo sea posible serializar todo junto, en ese caso no se cual seria el camino ideal para evitar problemas de memoria.

No es algo critico, la aplicacion es para algo muy especifico y personal pero me gustaria saber si hay alguna otra alternativa.

Saludos.
2  Programación / Programación General / Identificar metodos en OOP en: 15 Enero 2018, 17:45 pm
Estoy estudiando diseño de sistemas y me estoy comiendo la cabeza con la definición de algunos métodos. Lo que me cuesta identificar es quien debe llevar a cabo algunos métodos.

El escenario con el que estuve practicando es muy simple: "Un laboratorio de analisis clinicos ha comenzado el desarrollo de un sistema para la registracion de los analisis realizados por sus pacientes y el profesional que los solicita".

Partiendo de eso identifique cuatro clases: Paciente, Medico, Laboratorio y Analisis.
  • Paciente: representa una persona que se atiende en el laboratorio
  • Medico: representa un profesional de la salud
  • Analisis: representa un estudio solicitado por un medico especifico para un paciente determinado
  • Laboratorio: representa la clinica donde los medicos realizan analisis a los pacientes

De ahi pase a realizar el digrama de clases UML teniendo en cuenta que:
  • Un paciente puede tener muchos analisis. El paciente debe conocer los analisis que se realizo
  • Un medico puede haber solicitado muchos analisis. Debe tener cuenta de los analisis que requirio



Mi problema es que ese diagrama no me convence porque no tengo forma de asegurar que cuando se ejecuta paciente.addAnalisis(a), el analisis a ya haya sido cargado en el laboratorio.

Para ponerlo de otra forma, cualquiera que tenga acceso a un objeto Paciente podria agregar un analisis al paciente sin cargar ese mismo analisis al laboratorio y/o medico correspondiente. Lo mismo pasaria para un medico, cualquiera que tenga una referencia al medico podria cargarle un analisis sin tambien agregarlo al laboratorio ni al paciente. Esto supongo que generaria mucha inconsistencia en el sistema.

Yo podria implementar esa logica en Laboratorio::addAnalisis(a: Analisis), pero de nuevo, nada impide que alguien se salte esto y lo agregue manualmente.


Entonces mi otra solucion fue elminar los metodos addAnalisis y getListaAnalisis tanto de medico como de paciente, y luego agregar dos metodos a Laboratorio:
  • getAnalisisByPaciente(p: Paciente): Analisis[0..*]
  • getAnalisisByMedico(m: Medico): Analisis[0..*]

En este caso solo podria agregar analisis desde la clase Laboratorio, y asi implementar toda la logica necesaria en un solo lugar. Verifico que el medico y paciente asignado al analisis existan y luego lo agrego a la lista.
El problema es que ahora no estaria reflejando lo de que un paciente y un medico tienen que llevar cuenta de los analisis realizados.

Entonces no se como es la forma correcta de resolver esto.

Quizas no me deberia importar que alguien pueda llamar a Paciente.addAnalisis() y me estoy complicando por nada

Perdon por la falta de coherencia en todo esto pero tengo una ensalada en la cabeza y no se como explicarlo mejor. Saludos
3  Programación / Ingeniería Inversa / [Actualizado] Determinar que tipo de compresión utiliza un programa en: 8 Marzo 2017, 08:46 am
EDIT2: El algoritmo resulto ser LZO.
Cualquiera que necesite informacion sobre su funcionamiento hay algo aca:
https://www.kernel.org/doc/Documentation/lzo.txt

Lastimosamente sin ingenieria inversa no se puede obtener informacion de como funciona, en ningun lado hay una especificacion oficial.


Buenas, estoy en el proceso de hacer ingenieria inversa al protocolo de red de un mmorpg.

Algunos paquetes que suelen ser muy largos se comprimen con un algoritmo que estuve analizando pero no puedo determinar cual es (el cliente solo los descomprime, nunca comprime un paquete para enviarlo, por lo tanto no tengo acceso al proceso de compresion)
Todavia sigo creyendo que es una variante del LZ77 pero no logro dar con cual, lei el funcionamiento de varias pero no encuentro un parecido a ninguna (y tampoco creo que sea viable ponerme a probar todas porque seria dificil dar con el resultado exacto).

Tambien utilice extensiones del ida pro pero no tuve buenos resultados. Se menciona Deflate y unlzx pero ninguna de las referencias es utilizada dentro del proceso de descompresión.

Voy a intentar explicar lo mas claro posible como funciona el proceso, a ver si alguno me puede dar una mano. Se que seria facil simplemente reconstruirlo tal cual me muestra el hex rays y listo, pero mas me mata la curiosidad de saber cual es y quisiera poder implementarlo al 100%


Detalles:
Por lo que pude observar del algoritmo siempre trabaja sobre el buffer de entrada y de salida. Nunca utiliza alguna tabla/string o lo que fuese externo a estos dos.
Utiliza punteros (tal como el lz77 y sus variantes) para indicar el desplazamiento hacia atrás desde la posición actual. La información que tienen los punteros esta definida a nivel de bits.
Siempre que descomprime lo hace en base a lo que fue escribiendo en el buffer de salida. Del de entrada solo va tomando los pares de bytes que representan los punteros.
Desde mi parecer la descompresión es obligatoriamente secuencial, no hay posibilidad de saber dinamicamente donde hay otro puntero, al menos sin haber analizado los punteros anteriores.
Al comienzo de la cadena comprimida siempre hay un par indicando que es lo que viene.
El factor de compresion, al menos para el unico paquete que analice (lo hice varias veces pero siempre trae la misma informacion) es de casi el 50%.

Algoritmo:
Voy a intentar explicarlo a grandes rasgos (es posible que me saltee algunas partes).
Si quieren ver el algoritmo en c sacado de hex rays lo pueden hacer aqui:
https://gist.github.com/FYGonzalo/a4118d35620d48bacea2253d5aa48e6d

Las variables las renombre yo, puede que alguna tenga un nombre que no la represente. Tambien hay algunos comentarios del codigo, igual no se si sera mas entendible leer mi "pseudocodigo" o el codigo directo del hex rays.

Mas abajo adjunto una parte del proceso de descompresión de un paquete.

Al comenzar analiza el primer byte (de ahora en mas firstByte) del buffer de entrada (de ahora en mas inputBuffer).
Si este es mayor a 0x11 (17): // Significa que hay bytes descomprimidos y se deben copiar tal como estan
    Le resta 0x11 (17) al firstByte y el resultado indica la cantidad de bytes por copiar.
    Avanza una posicion en el inputBuffer (la siguiente al firstByte) y copia lo que indica el resultado anterior.
    Dependiendo cuanto fue el resultado salta a un label donde sigue haciendo analisis del par de bytes.
Sino
LABEL 1
    Lee en una variable "secondByte" el segundo byte del inputBuffer
    Si el firstByte es menor a 0x10 (16)
        Si el firstByte es nulo
            Si el secondByte es nulo
                -----
            firstByte = secondByte + 15
        Copia una DWORD del inputBuffer al outputBuffer y avanza los punteros (de ambos buffer) 4 posiciones
        Asigna a un contador el valor de firstByte - 1
        En base al valor del contador itera copiando bytes del inputBuffer al outputBuffer (sin modificarlos)
        Vuelve a leer del inputBuffer otro par (firstByte & secondByte)
        Si el firstByte es menor a 0x10 (16)
            ------
    Mientras (1)
        Si firstByte es mayor a 0x40
            Obtiene un puntero al outputBuffer retrocediendo ((-((firstByte >> 2) & 7) - 1) - secondByte * 8) posiciones

Pausa. Aca se observa una de las situaciones en donde se opera el par en base al valor de sus bitss.
En un caso que detallo mas abajo, el par que se trabaja es (4C, 01)
El valor en bits de 4C es: 0100 1100
Aplicamos el shift de 2 posiciones: 0001 0011
Aplicamos el and 7: 0001 0011 & 0000 0111 = 0000 0011
Sumamos 1 (en realidad es resta, pero son ambos negativos asi que lo obviamos): 0000 0100.

La conclusion que saque de esta operacion (y de otras donde se repite) es que en el firstByte, cuando es mayor o igual a 0x40, hay 3 bitss que indican parte del desplazamiento.
En este caso seria: 0100 1100
Pero como luego se le suma 1 sabemos que el primer termino, de la operacion compleja indicada en la ultima linea de codigo mas arriba, dara como resultado un valor entre 1 y 8 (no mas ni menos).

Luego simplemente se suma (nuevamente, es una resta pero al ser todos negativos lo obviamos) el valor del secondByte (sin importar cual fuere) multiplicado por 8.
Es decir que al final vamos a retroceder en el outputBuffer la cantidad resultante de esta suma.

           Avanza el inputBuffer posicionandose en el byte siguiente al par que estamos analizando
            Determinamos la cantidad de bytes por copiar* aplicando ((firstByte >> 5) - 1)        

Nuevamente nos detenemos aqui.
Recordemos que el firstByte actualmente tiene el valor 4C que en binario es: 0100 1100.
Aplicamos el shift 5 posiciones a la derecha: 0000 0010
Le restamos 1: 0000 0010 - 0000 0001.

La conclusión de este segmento es que los 3 bitss de mayor peso del firstByte (siempre que este sea mayor a 0x40) indican una cantidad de bytes por copiar*.
*En realidad no indica la cantidad total de bytes por copiar. Obligatoriamente al llegar a este punto se copian al menos 2 bytes (lo veran en las siguientes lineas de codigo), pero indica la cantidad de bytes, luego de haber copiado 2 obligatorios, que se deben copiar.

           Copiamos dos bytes obligatorios del outputBuffer (basados en el puntero que obtuvimos anteriormente hace 4 lineas de codigo)
            Luego copiamos tantos bytes del outputBuffer como indique la operacion anterior.
            Luego saltamos a otro label donde aplicamos una and entre el firstByte y 3. El resultado indica la cantidad de bytes (planos) del inputBuffer por copiar. En caso de que sea 0, volvemos al Label 1, sino continuamos en el while.

Nuevamente se opera a nivel de bits.
Al aplicar la operacion and entre el valor de firstByte y 3 (0000 0011) lo que hacemos es analizar los dos bits de menor peso del firstByte.
Es decir que ahora como conclusión entendemos que significa completamente el firstByte cuando es mayor o igual a 0x40:
0100 1100: Indican parte de la cantidad de bytes a copiar del "diccionario" (recordemos que se le resta 1) y obligatoriamente se copiaban 2
0100 1100: Indican parte del desplazamiento hacia atras en el outputBuffer donde se encuentra la cadena descomprimida (recordemos que se le suma 1 y luego 8 * secondByte)
0100 1100: Indican la cantidad de bytes planos del outputBuffer que debemos copiar luego de haber copiado los "descomprimidos".

       Si el firstByte es menor a 0x20 (32)
            Break (sale del while y creo que termina con algunas operaciones)
        (Si el firstByte es menor que 0x40 pero mayor o igual a 0x16 - Condicion no especificada pero se llega a este punto debido a esa situacion)

En este caso se da una situacion particular. Es como si se invirtieran la responsabilidad de los bytes del par y ahora el segundo byte (secondByte) indica los desplazamientos hacia atras en el outputBuffer y el firstByte los bytes por copiar.

           Se obtiene una "cantidadCopiar" haciendo firstByte & 0x1F

Aqui nuevamente se vuelve a trabajar a nivel de bitss.
Un caso que analice en el cual se entraba a este punto es con el par (2A, C8).
Como dijimos anteriormente cuando el firstByte es menor a 0x40 pero mayor o igual a 0x20 se invierten las responsabilidades.
Sabemos que 2A es: 0010 1010
Y 1F: 0001 1111

Asi que al aplicar la operacion and entre ambos lo que estamos haciendo es recuperar los 5 bitss de menor peso del firstByte.
El resultado sera 0000 1010

           Si cantidadCopiar es nula
                Si secondByte es cero
                    -----
                cantidadCopiar += secondByte + 31 (decimal)
            Obtenemos un puntero al outputBuffer con un retroceso desde la posicion actual determinado por ((secondByte >> 2) + 1)

Nuevamente se trabaja con bitss.
Recordemos, secondByte es C8: 1100 1000
Aplicamos el shift: 0011 0010 (50 decimal)
Restamos 1: 0011 0001 (49 decimal)

           Avanzamos el inputBuffer 2 posiciones (nos saltamos un byte despues del par que estamos analizando)
            --- Se aplica una operacion rara dada una condicion que nunca vi que fuese verdadera bajo el inputBuffer de prueba que estoy analizando ----
            Copiamos una DWORD de la posicion que indica el puntero que definimos unas lineas atras (del outputBuffer) y lo pegamos en la posicion actual del outputBuffer. Es decir, copiamos una DWORD "descifrada" del outputBuffer a la posicion actual del outputBuffer (basicamente buscamos en el diccionario la palabra y la pegamos)
            Avanzamos 4 posiciones (por el DWORD) en los punteros a ambos buffers.
            Disminuimos la cantidadCopiar en 2
            Hacemos un bucle copiando la cantidad de bytes que indique "cantidadCopiar"

            Nuevamente (como el caso de mayor o igual a 0x40): (Basicamente es un label que no lo puse como tal)
            Aplicamos un and entre el byte que indica el offset (ahora es el secondByte, en el caso anterior habia sido firstByte) y 3. El resultado indica la cantidad de bytes "planos" restantes por copiar del inputBuffer al outputBuffer.

Otra vez trabajamos a nivel de bits.
Al aplicar el and al secondByte (0xC8) lo que estamos haciendo es recuperar los 2 bitss de menor peso.

Recapitulando ahora conocemos toda la informacion que trae el secondByte:
0011 0010: Indican el desplazamiento hacia atras en el outputBuffer (recordemos que se le resta 1)
0011 0010 Indican la cantidad de bytes "planos" que deben copiarse del inputBuffer al outputBuffer, luego de haber copiado los del diccionario indicados por el puntero.

           En caso de que este resultado sea mayor que 0, copiamos los bytes que indican y seguimos dentro del while.
            En caso contrario (sea igual a 0), volvemos al LABEL 1.

Ya cuando se sale de todo este bucle (unicamente por el Break de que firstByte < 0x20) se hacen operaciones para finalizar, se copian los bytes restantes y algun que otro detalle.
Se devuelve la longitud del buffer de salida.

Descompresion de un paquete real:
Lo pueden ver aqui, hay imagenes y una explicacion del proceso hasta cierto punto (no lo cargo al post porque se haria mucho mas largo de lo que ya es).
http://imgur.com/a/kuQkl




Y eso es todo lo que pude obtener, la verdad es que hay algunos detalles mas del algoritmo pero no llegue a analizarlos porque mi principal objetivo es determinar que estandar de compresion (si es que es un estandar) es el utilizado.

Espero no haberlos aburrido, y que me puedan dar una mano, me costo mucho trabajo hacer la ingenieria inversa y luego un poco mas redactar todo el post y juntar las pruebas.

Saludos.
4  Programación / .NET (C#, VB.NET, ASP) / Serializar objetos en XML (XmlSerialization, XDocument, XmlWriter, etc) en: 1 Marzo 2017, 00:42 am
Estoy escribiendo un Packet Sniffer y lo que quiero hacer es cada vez que capturo un paquete, serializarlo a un archivo XML para poder procesarlo mas tarde.

Estuve analizando usar XmlSerialization que fue lo primero que encontre en google pero mi problema es que, por lo que vi, esta pensado para que cada vez que se serializa un objeto, este se guarde en un nuevo archivo (lo digo por el hecho de que escribe el archivo completo, incluyendo el namespace y etc). Si utilizo esto lo que ocurre es que tengo que mantener en memoria todos los paquetes que vayan llegando hasta que el usuario quiera dejar de capturar y luego recien escribir el archivo (uso excesivo de memoria).

Mi primera idea fue que cada vez que llegue un paquete, escribirlo en el archivo y liberar ese objeto, por lo que me parece que XDocument puede ser util en este caso, solo que voy a tener que escribir manualmente el proceso de serialización.

Basicamente lo que me gustaria saber, si ya manejaron la serialización xml, como me recomiendan haga este proceso.

Saludos
5  Seguridad Informática / Hacking / Seguridad adicional en tarjetas Mifare Classic en: 28 Julio 2016, 05:06 am
Buenas a todos.

Tengo un conocido que trabaja (no pertenece al area de sistemas) en una empresa de transportes (no quiero dar muchos detalles para no tener problemas) que esta preocupado porque se entero que en una ciudad estan cargando tarjetas de transporte de otra empresa de forma ilegal y tiene dudas sobre si no esta pasando lo mismo en su empresa.

Como entusiasta que soy me puse a investigar sobre el tema y tengo entendido que las tarjetas que usan son las Mifare Classic de 1k. Lei por completo el tema que hay en este foro del año 2009 y segui googleando, obviamente me entere que son facilmente hackeables en poco tiempo.

Le comente todo lo que encontre y me dijo que hablo con el gerente de sistemas y le dijo lo siguiente:
"Me dijo que [CIUDAD DE LA EMPRESA DONDE TRABAJA] es distinto porque modificaron la estructura de la tarjeta y que el código son 6 dígitos por lo que se tardaría 11 años en encontrar la clave.. Y que además tiene una firma que calculo son otros dígitos mas.
Pero la de [OTRAS CIUDADES QUE USAN MIFARE] dijo el que pudo romper en 4 dias, Y el teniendo el primer numero, saco por fuerza bruta"

Por lo que es obvio que cuando se refiere a que modificaron los 6 digitos hace referencia a una de las claves a o b de los sectores y que cuando habla de fuerza bruta hace referencia al metodo "darkside"
Y calculo que cuando se refiere a la firma es algun metodo de crifrado sobre la info del sector que utilizan.

Ahora, la cosa es que este conocido dice que el area de sistemas es un tanto soberbio y que no esta seguro de todo lo que le dicen, entonces le explique los metodos de seguridad que considero que pueden tener pero al fin y al cabo la mayoria son corrompibles.

Lo unico probablemente seguro seria que la informacion de la tarjeta, cada vez que se realice una transaccion se valide con un servidor, pero siendo transportes en constante movimiento creo que no se pueden valer de una conexion en tiempo real todo el tiempo.
Y lo de que se encuentre cifrado tampoco es muy claro porque tranquilamente podria cargar la tarjeta, guardar el dump y cuando se termine el credito volver a pegar ese dump (a menos que tenga algun tipo de seguridad adicional).

Al fin y al cabo lo que me gustaria saber es si alguno de ustedes conoce algun caso practico donde se le haya agregar mayor seguridad a las tarjetas mifare classic, porque lo que me hace ruido es que si en paises importantes como chile o mexico (o incluso paises europeos) se pudo hackearlas, entonces que tanto pudo haber hecho una empresa de por acá como para darle esa seguridad a las tarjetas mifare classic que al final nunca llegaron a tener.

Soy tan solo un chico de 21 años y siento que es muy probable que le este llenando de paranoia a mi amigo (no me creo tan inteligente como para poder burlar al area de sistemas de una empresa importante) pero es que hay muchas cosas que me hacen ruido.

Mi objetivo es basicamente saber si existe la chance de que ellos (el area de sistema) le haya agregado la seguridad necesaria a la tarjeta o solo lo dice para que mi conocido no rompa los huevos.
Probablemente la unica forma de saber esto sea que yo me ponga a probar pero no tengo el lector.

Saludos y gracias de antemano.

6  Programación / Java / [Ayuda] Me cuesta comprender sobre Java EE en: 19 Abril 2016, 17:59 pm
Hola.
En la facultad nos pidieron que desarrollemos una aplicación web un poco compleja, básicamente para que utilicemos Java EE 7 (JPA, JDBC, Servidor de mail, etc).
Estuve leyendo y viendo algunos videos y todavia no logro imaginarme como sera mi proyecto.
Por lo que lei se recomienda utilizar maven para la gestion y estructuracion del proyecto por lo que busque y me encontre con esto:
https://maven.apache.org/plugins-archives/maven-archetype-plugin-1.0-alpha-7/examples/j2ee-simple.html

Y lo que me marea es que no se como organizo mi aplicacion bajo esa estructura. Digo esto porque me vi un tutorial (no muy bueno) de codigo facilito y en primer lugar habla sobre crear un sistema bajo java ee pero empieza el proyecto como un web application solamente, y despues habla sobre el mvc y lo unico que hace es dividir el proyecto asi
.
|
|--WebPages
|  |--index.jsp
|
|--SourcePackages
|  |--modelo
|  |  |--conexion.java
|  |
|  |--servlet
|  |  |--controlador.java

Y no me parece que un proyecto de Java EE se diseñe asi, no se exactamente como explicarlo pero siento que no es la forma de encarar un proyecto.

Alguien me podria encaminar un poco? Gracias
7  Programación / Ingeniería Inversa / Inyeccion DLL para extender una funcion en: 28 Octubre 2015, 00:34 am
Estoy intentando capturar un mensaje que posteriormente sera un packet antes de que se encripte.
Tengo la direccion estatica de la funcion que quiero modificar, entonces mediante el siguiente algoritmo modifico el codigo para que cuando ingrese a esa funcion salte a mi codigo.
Código
  1. void JmpPatch(void *pDest, void *pSrc, int nNops = 0) {
  2.  
  3. DWORD OldProt;
  4. VirtualProtect(pSrc, 5 + nNops, PAGE_EXECUTE_READWRITE, &OldProt);
  5. PointTo = (DWORD)pSrc + 8;
  6. *(char*)pSrc = (char)0xE9;
  7. *(DWORD*)((DWORD)pSrc + 1) = (DWORD)pDest - (DWORD)pSrc - 5;
  8.  
  9. for (int i = 0; i < nNops; ++i) { *(BYTE*)((DWORD)pSrc + 5 + i) = 0x90; }
  10.  
  11. VirtualProtect(pSrc, 5 + nNops, OldProt, &OldProt);
  12. }

El codigo funciona bien, salta a mi funcion, entonces lo que hago es ejecutar las instrucciones que habia reemplazado y despues volver a donde estaba (estoy haciendo pruebas solamente).

Esta es la funcion original en Assembler (yo coloco el jmp en 0x626324 y hago nop de dos bytes mas) y mas abajo estas la funcion mia a la que salto.

Código
  1. DWORD dir = 0x62632B;
  2. void ImprimirLog()
  3. {
  4. __asm {
  5. mov edi, [esp + 4 + DWORD PTR 0Ch]
  6. shr edi, 2
  7. push dir
  8. ret
  9. }
  10. }

El problema es que cuando llego a mi funcion se me cambian todos los registros de la cpu y el stack, y se me hace un desastre y cuando hago el return se me corrompe todo.

Esto es antes de llegar a __asm { }


Y asi queda cuando entra a __asm { }



No tengo idea en que estoy fallando, ya probe un monton de cosas y quede ahi trabado.
8  Programación / Ingeniería Inversa / Inyeccion de DLL para obtener acceder a parametros de una funcion en: 25 Octubre 2015, 14:57 pm
Ya hace mucho que vengo jodiendo con querer hacer un server emulator de un juego online (no existe ningun emulador). Cada vez que empiezo lo dejo al tiempo, aunque siempre avanzo un poquitito mas. Hoy se repite la historia...

Cuando arranque (a comienzo de año) me habia dado cuenta que los paquetes estan cifrados, y con el OllyDBG pude encontrar el algoritmo de encriptacion (muy simple).

Cuando me conecto al servidor, el mismo envia una clave de 16 bytes que todavia no se como se genera pero no importa.
Cada vez que el cliente tiene que enviar un mensaje, realizar una operacion XOR entre una DWORD del mensaje y una DWORD de la clave, la DWORD de la clave se elige mediante un algoritmo tonto que ahora no lo recuerdo.
Luego de cifrar el mensaje se suma a cada DWORD de la clave la longitud del mensaje cifrado. (En realidad no es la totalidad de la longitud, si el mensaje tiene una longitud de 0x38, entonces suma 0x30, no se como llamarlo)

Y se repite todo por cada mensaje enviado.
Entonces lo siguiente que debia hacer era desencriptarlos e interpretarlos.

En ese momento se me habia ocurrido (debido a mis pocas capacidades pensativas) hacer un programa en el cual al ingresar la clave, el numero del mensaje (ej, mensaje 5) y el mensaje, este me devuelva el mismo descifrado.
Me dispuse a hacerlo pero me frustro perder tanto tiempo teniendo que convertir datos para poder tratarlos, para poder ponerlos en los componentes de la GUI, etc, asi que deje todo a la *****.

Hoy retomando me di cuenta que lo mejor que podria hacer es interceptar la funcion que lo cifra (o descifra) y guardar el mensaje en un log antes de encriptarlo, asi puedo tomar muchisimas muestras y analizarlas facilmente.

Estuve leyendo sobre la inyeccion de DLLs pero hay cosas que no me quedan muy en claro.
La funcion a la que quiero acceder (basicamente para extenderla) no son del sistema, son del juego sobre el cual estoy trabajando.
Leyendo un par de cosas en google se me ocurrio que lo ideal seria obtener la direccion de memoria donde esta la funcion (creo que es fija) y luego sustituir alguna instruccion con un jump a la DLL que yo inserto.
Ya dentro de mi funcion tendria que acceder a los parametros (un buffer y la longitud del buffer) de la funcion la cual intercepte y es eso lo que no se como tengo que hacer.
Segun tengo entendido los parametros, en assembler, se pasan por el Stack y luego son recuperados por la funcion que se ejecuta, entonces yo deberia saltar a mi funcion en la primera instruccion, sacar todos los parametros, procesarlos y despues volver a volcarlos en el Stack, eso es correcto?

Y algo relacionado pero a parte, mi idea es ir capturando ese buffer cada vez que se va a mandar un mensaje e ir guardandolo en un log (xml).
Como tendria que hacerlo? Porque si lo hago en mi funcion cada vez que llegue tendria que abrir el log, escribir el buffer y algunos datos mas, y despues cerrar el archivo, creo que no seria lo optimo teniendo en cuenta que haria esto todo el tiempo que se envian paquetes.

Saludos.
9  Programación / Scripting / [Python] Emular servidor, ¿Funcionará? en: 24 Enero 2015, 20:38 pm
Buenas a todos. Estoy en el proceso de armar un emulador del servidor de un juego (aclaro que no existe ninguno de dicho juego, estoy con la ingenieria inversa). El progreso recién es casi del 2%, lo único que tengo por ahora son datos mínimos que si los uso bien, podre hacer el resto.
Entonces quería comenzar a desarrollar el servidor para ir armando una estructura base e ir probando los paquetes que ya los conozco.

Mi duda es si Python funcionara como lenguaje para emular el servidor o tendré que mirar para otro lado (Pense en C# pero no me gusta la sintaxis).
 
Yo creo que el servidor, con soportar hasta 10.000 personajes, es susficiente (y estoy exagerando).

No es que elija Python por que es multiplataforma, solo lo hago porque me gusta la sintaxis.

¿Creen que funcionará?

10  Programación / Ingeniería Inversa / [OllyDBG] ¿Mensaje cifrado o codigo hexadecimal no ascii? en: 20 Enero 2015, 06:04 am
Buenas!
Mi presentacion
¿Que conocimientos tengo? Soy estudiante de Ing. en sistemas de informacion, apenas pasando al 3er año pero con conocimientos basicos -> medios (para no exagerar) de programacion, programé en C# y Python (todo lo hago por hobby, no trabajo), y tuve que analizar un codigo en C. También conozco assembler para el microcontrolador PIC 16x84, asi que entender a grandes rasgos assembler de x86 no es una tarea muy complicada.

Introduccion al problema.
Hace poco se me dio la idea de intentar hacer un emulador de un juego online que me dio muchos vicios años atras (el juego aun sigue funcionando). Estas son las cosas que fui probando:
1- Obtener el source del cliente. Está escrito en C++ v6, y segun lei en internet es imposible decompilar. Descarté esta opcion.
2- Por la anterior, se me ocurrio que seria buena idea interceptar los paquetes y asi comenzar a hacer el emulador, viendo que datos eran enviados y como debia comportarse. ¿El problema? Los paquetes se encuentran cifrados.
3- Googleando me encontre con un pdf que explica bastante bien los caminos que hay que seguir para hacer un emulador http://cellframework.sourceforge.net/uploads/Introduction%20to%20Server%20Side%20Emulation.pdf (lo adjunto para alguien que este en mi misma situacion)
En ese pdf dicen que la mejor manera para comprender los paquetes es viendo como los descifra el cliente. Entonces segui mi camino con el OllyDBG, viendo tutoriales y haciendo pruebas hasta que pude dar con la sección del cliente que cifra el código (y pude obtener el algoritmo, a medias, pero ya lo tengo 'encerrado').

Situacion actual:
Como dije, logre dar con la parte del codigo que cifra el mensaje a ser enviado por el cliente. Por ahora solo probé mientras iniciaba sesión a mi cuenta, y logre ver la parte donde dice mi nombre de usuario y la contraseña, pero el resto del mensaje se ve con simbolos raros (el mensaje antes de cifrar se ve así, y despues obviamente por la encriptacion se ve raro), entonces mi duda es: ¿Puede ser que el mensaje que se envia no este codificado en ASCII y por ello se ve de esa manera? Lo digo porque el juego tengo entendido que esta hecho por taiwaneses, y entonces el codigo ASCII no puede mostrar los caracteres correctamente debido a que no tiene el alfabeto de esos lugares.
En el caso de que sea como lo planteo, ¿Conocen que tipo de codificacion?
Gracias!


Páginas: [1] 2 3
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines