Dudas con Integer Overflow

Iniciado por Vaagish, 2 Septiembre 2015, 23:45 PM

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

Vaagish

Hola chicos!

Estoy lidiando con un programa que tiene un fallo de integer overflow y no soy precisamente un 'experto' en estos temas del reversing.. u.u

Me estoy basando en este texto para aprender sobre el asunto: http://phrack.org/issues/60/10.html

Por lo que entiendo en este code (que esta muy bien explicado):

Código (cpp) [Seleccionar]
    /* width1.c - exploiting a trivial widthness bug */
    #include <stdio.h>
    #include <string.h>

    int main(int argc, char *argv[]){
            unsigned short s;
            int i;
            char buf[80];

            if(argc < 3){
                    return -1;
            }

            i = atoi(argv[1]);
            s = i;

            if(s >= 80){            /* [w1] */
                    printf("Oh no you don't!\n");
                    return -1;
            }

            printf("s = %d\n", s);

            memcpy(buf, argv[2], i);
            buf[i] = '\0';
            printf("%s\n", buf);

            return 0;
    }


El problema esta cuando se le pasa como argumento a ese programa un numero mayor que 65535, ya que luego se va a tratar como un "unsigned short",, aca el disassembly:

Código (asm) [Seleccionar]
CPU Disasm
Address   Hex dump                  Command                                  Comments
009012B8  |.  FF73 04               PUSH DWORD PTR DS:[EBX+4]                ; /Arg1 = ASCII "65536"
009012BB  |.  FF15 B8309000         CALL DWORD PTR DS:[<&MSVCR120.atoi>]     ; \MSVCR120.atoi
009012C1  |.  8BF8                  MOV EDI,EAX
009012C3  |.  83C4 04               ADD ESP,4
009012C6  |.  66:83FF 50            CMP DI,50
009012CA  |.  72 17                 JB SHORT 009012E3
009012CC  |.  68 8C319000           PUSH OFFSET 0090318C     ; "Oh no youdon't!"
009012D1  |.  FF15 B4309000         CALL DWORD PTR DS:[<&MSVCR120.printf>]
009012D7  |.  83C4 04               ADD ESP,4
009012DA  |.  83C8 FF               OR EAX,FFFFFFFF
009012DD  |.  5F                    POP EDI
009012DE  |.  5B                    POP EBX
009012DF  |.  8BE5                  MOV ESP,EBP
009012E1  |.  5D                    POP EBP
009012E2  |.  C3                    RETN
009012E3  |>  0FB7C7                MOVZX EAX,DI
009012E6  |.  50                    PUSH EAX
009012E7  |.  68 A0319000           PUSH OFFSET 009031A0    ; ASCII "s = %d"
009012EC  |.  FF15 B4309000         CALL DWORD PTR DS:[<&MSVCR120.printf>]


Bueno, a mi entender el mayor problema es la linea 7. Comparar el valor 10000 con 50 (hexadecimal), el programa se saltea el " if (s >= 80) " y luego falla en memcpy, mas precisamente aca:

Código (asm) [Seleccionar]
CPU Disasm
Address   Hex dump                   Command                                            Comments
58D2F608  />  F3:A5                  REP MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI]


Se copia de esi a edi un valor muy grande y su respectiva violacion de segmento.

En el texto aclara esto:

CitarInteger overflows are not like most common bug classes.  They do not allow
direct overwriting of memory or direct execution flow control, but are much
more subtle.  The root of the problem lies in the fact that there is no way
for a process to check the result of a computation after it has happened,
so there may be a discrepancy between the stored result and the correct
result.  Because of this, most integer overflows are not actually
exploitable.  Even so, in certain cases it is possible to force a crucial
variable to contain an erroneous value, and this can lead to problems later
in the code.

Y tambien aclara esto:

CitarThe length argument is taken from the command line and held in the integer
i.  When this value is transferred into the short integer s, it is
truncated if the value is too great to fit into s (i.e. if the value is
greater than 65535).  Because of this, it is possible to bypass the bounds
check at [w1] and overflow the buffer.  After this, standard stack smashing
techniques can be used to exploit the process.

Cuando yo pruebo el programa que estoy tratando de arreglar, a veces logro ejecutar los tipicos '41414141' y otras veces no, o sea.. el programa falla en direcciones diferentes todas las veces, tiene remedio eso? Puedo forzar la direccion donde quiero que falle??

1 - Yo me quedo con la duda de como es posible que sin saber el resultado final del buffer igual sea posible ejecutar codigo arbitrario.. dice que con metodos estandar se puede, pero yo no encuentro forma..

2 - Asi que no siempre es explotable esta situacion?

Gracias por leer todo eso!! Saludos!!!

Vaagish


someRandomCode

Se me ocurre que el problema esta en el memcpy de argv[2] pero realmente estoy tambien bastante verde en el tema de reversing..

.:UND3R:.

Que SO estás usando, con qué parámetros compilaste el programa?, me encantaría ayudarte pero no dispongo de mucho tiempo, creo haber estudiado algo de Integer Overflow, saludos.

Solicitudes de crack, keygen, serial solo a través de mensajes privados (PM)

Vaagish

Hi!  :D

Gracias por responder chicos! Les cuento hasta donde entiendo..

CitarSe me ocurre que el problema esta en el memcpy de argv[2] pero realmente estoy tambien bastante verde en el tema de reversing..

En realidad entiendo porque falla el programa, digamos que tiene un "mal diseño",, y me explico mejor:

1 - i es integer y se obtiene desde la consola (argv[1])
2 - si el valor introducido es (por ejemplo) 65536,, cuando se hace i = atoi(argv[1]); i vale 10000
3 - cuando se pone en s el valor de i, s solo puede guardar los ultimos 4 valores (0000), por lo cual la condicion de la linea 17 es salteada.
4 - Luego se copia a buf, pero con el valor de i que es mucho mayor,, y.. buffer overflow.

CitarQue SO estás usando, con qué parámetros compilaste el programa?, me encantaría ayudarte pero no dispongo de mucho tiempo, creo haber estudiado algo de Integer Overflow, saludos.

Estoy desde windows, lo compile en visual studio 2013 con la seguridad desactivada..

Lo que yo quisiera saber es si este tipo de situacion es explotable,, si existe una forma de controlar el fallo y poder ejecutar codigo arbitrario.. a memcpy se le pasa un valor grande para copiar (10000) y el buffer (buf) se desborda porque solo tiene 80,, pero como se puede llegar a "sacar ventaja" del buffer overflow es lo que me esta intrigando mucho  :laugh:

Entiendo que el "shellcode" tendria que ser pasado por argv[2].  :rolleyes:

Saludos!!! Gracias!

PD: Este codigo es un ejemplo de integer overflow, el fallo que yo busco esta en otro programa, pero es comparable uno con otro. No es que precise arreglar ese codigo, ni es mio.. digo por las dudas..

MCKSys Argentina

#5
Hola!

Hasta donde entiendo, el integer overflow de este caso, lo usas para escribir más cantidad de heap con tu data, que la prevista.

En lo único que veo a ésto útil, es si dentro de la parte de heap que has pisado, hay algún puntero a función, que sea usado por el código siguiente (o que puedas triguerear sin que se rompa el proggie).

Creo que es la única forma de explotar este tipo de cosas...

Saludos!

PD: Si es por prevenir este tipo de cosas: Ten en cuenta que todos los martes salen parches de M$, y varias veces son integer overflow. Eso te dice que es difícil (no imposible) detectarlos. Un ejemplo de hace 4 días...  :xD
MCKSys Argentina

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


Vaagish

Hi!!

CitarHasta donde entiendo, el integer overflow de este caso, lo usas para escribir más cantidad de heap con tu data, que la prevista.

Exacto!

CitarEn lo único que veo a ésto útil, es si dentro de la parte de heap que has pisado, hay algún puntero a función, que sea usado por el código siguiente (o que puedas triguerear sin que se rompa el proggie).

Ok, algo entendi.. ¿pero que ventaja tendria si he pisado el puntero a funcion? No se que es triguerear,, algo como juntar trigo? xD

Bueno, ya igual me voy haciendo la idea que esta muy complejo esto.. y que un integer overflow a veces y solo a veces es explotable, digamos.. si se alinean los planetas..

CitarSi es por prevenir este tipo de cosas: Ten en cuenta que todos los martes salen parches de M$

Dudo que vuelva a buscar un integer overflow en mi vida xD

Gracias!! Saludos!!

MCKSys Argentina

Cita de: Vaagish en  8 Septiembre 2015, 20:23 PM
Ok, algo entendi.. ¿pero que ventaja tendria si he pisado el puntero a funcion? No se que es triguerear,, algo como juntar trigo? xD

triguerear es desencadenar/provocar. Es la adaptación de la palabra inglesa trigger. Sería lo que se necesita hacer para que la vulnerabilidad "se dispare".

Admito que no es lo mejor, pero cuando hablamos sobre cosas referentes a la informática, muchas veces debemos mezclar inglés con castellano sólo por el hecho de que nos entiendan. Aunque éste no sea el caso  :P

Ejemplos: montículo en vez de heap, pila en vez de stack, etc. Algunas cosas no suenan bien si se traducen...

Saludos!
MCKSys Argentina

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


Vaagish

#8
Citarmuchas veces debemos mezclar inglés con castellano sólo por el hecho de que nos entiendan.

Comparto, es solo que no estoy tan familiarizado con la jerga de ingeniería inversa xD

Justo cuando entre a responder, el foro me propuso (ahi en mensajes similares) que vea el siguiente tema:

http://foro.elhacker.net/desafios_wargames/desafioreto_para_avanzados_explotacion_por_integer_overflow-t15164.0.html

Extraña coincidencia de la vida, el programa es bastante parecido a ese que puse de ejemplo,, y al parecer el reto es meter un shellcode! Asi que voy a ver si tiene solucion (que supongo que si, claro) para aprender sobre el tema.

Muchas gracias a todos! A seguir aprendiendo :)

EDITADO:

Parece que en el enlace que puse, Rojodos y p5il0cyb3 entran en duelo a muerte y no me termina de quedar claro si sirve o si no,, pero sigue siendo informacion util.

MCKSys Argentina

Cita de: MCKSys Argentina en  8 Septiembre 2015, 18:42 PM
Hasta donde entiendo, el integer overflow de este caso, lo usas para escribir más cantidad de heap con tu data, que la prevista.

Creo que entendí mal. Mirando el código, veo que el buffer es local, por lo que estará en el stack. Luego, al desbordarlo podrías pisar el return address y saltar a tu código; o bien, pisar el SEH chain y ROPear.

Aunque, bueno, habría que compilar y mirar con un dbg para sacar bien una solución; pero la 989898 es mayor...  :P

Saludos!

MCKSys Argentina

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