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
/* 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
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
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:
Citar
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.
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:
Citar
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.
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!!!