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.htmlPor lo que entiendo en este code (que esta muy bien explicado):
/* 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:
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:
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:
Integer 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:
The 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!!!