Posible error en inet_ntoa()

Practicando un poco sobre raw sockets y demás, he visto que en existe un error muy curioso en la función inet_ntoa() que es estandar dentro de libc.

Todo surgio a raiz de https://foro.elhacker.net/programacion_cc/pequeno_sniffer_en_c-t235639.0.html;msg1156524#msg1156524

No se si sea igual el codigo en linux, pero este ultimo al igual que freebsd tambien tiene la falla.

El codigo de inet_ntoa es el siguiente:

inet_ntoa(struct in_addr in) {
       static char ret[18];
 
       strcpy(ret, "[inet_ntoa error]");
       (void) inet_ntop(AF_INET, &in, ret, sizeof ret);
       return (ret);
}

inet_ntoa Manda llamar inet_ntop y esta a su vez a inet_ntop4


const char *
inet_ntop(int af, const void * __restrict src, char * __restrict dst,
   socklen_t size)
{
       switch (af) {
       case AF_INET:
               return (inet_ntop4(src, dst, size));
       case AF_INET6:
               return (inet_ntop6(src, dst, size));
       default:
               errno = EAFNOSUPPORT;
               return (NULL);
       }
       /* NOTREACHED */
}
 
 
static const char *
inet_ntop4(const u_char *src, char *dst, socklen_t size)
{
       static const char fmt[] = "%u.%u.%u.%u";
       char tmp[sizeof "255.255.255.255"];
       int l;
 
       l = snprintf(tmp, sizeof(tmp), fmt, src[0], src[1], src[2], src[3]);
       if (l <= 0 || (socklen_t) l >= size) {
               errno = ENOSPC;
               return (NULL);
       }
       strlcpy(dst, tmp, size);
       return (dst);
}


El problema creo yo que a la hora de poner esto en una direccion statica, al mandarlo a llamar 2 veces durante el mismo printf(), hace guarde en la pila 2 veces la misma direccion:

# gdb ./sniffer
GNU gdb 6.1.1 [FreeBSD]

(gdb) break 49

Breakpoint 1 at 0x8048309: file sniffer.c, line 49.
(gdb) run

Starting program: /usr/home/Anon/sniffer

Esperando paquetes...
 
Breakpoint 1, main () at sniffer.c:49

49 printf("[+] ICMP: %s\t->\t%s\n",inet_ntoa(iphead->ip_src),inet_ntoa(iphead->ip_dst));

(gdb) printf "0x%x\n", buff

0x28102000
(gdb) i r

eax            0x1 1
ecx            0xbfbfec98 -1077941096
edx            0x0 0
ebx            0x1 1

esp            0xbfbfecb0 0xbfbfecb0
ebp            0xbfbfecf8 0xbfbfecf8
esi            0xbfbfed40 -1077940928
edi            0x0 0

eip            0x8048309 0x8048309
eflags         0x246 582
cs             0x33 51
ss             0x3b 59

ds             0x3b 59
es             0x3b 59
fs             0x3b 59
gs             0x1b 27

(gdb) x/4 0xbfbfecb0

0xbfbfecb0: 0x00000003 0x28102000 0x00010000 0x00000000
(gdb) step          

[+] ICMP: 74.125.95.147 -> 74.125.95.147

52 break;
(gdb) x/4 0xbfbfecb0

0xbfbfecb0: 0x08062664 0x08066e98 0x08066e98 0x00000000
(gdb) printf "%s\n", 0x08062664

[+] ICMP: %s -> %s

 
(gdb) printf "%s\n", 0x08066e98

74.125.95.147
(gdb) x/4 0xbfbfecb0

0xbfbfecb0: 0x08062664 0x08066e98 0x08066e98 0x00000000
 # gdb ./sniffer
GNU gdb 6.1.1 [FreeBSD]

(gdb) break 49

Breakpoint 1 at 0x8048309: file sniffer.c, line 49.
(gdb) run

Starting program: /usr/home/Anon/sniffer

Esperando paquetes...
 
Breakpoint 1, main () at sniffer.c:49

49 printf("[+] ICMP: %s\t->\t%s\n",inet_ntoa(iphead->ip_src),inet_ntoa(iphead->ip_dst));

(gdb) printf "0x%x\n", buff

0x28102000
(gdb) i r

eax            0x1 1
ecx            0xbfbfec98 -1077941096
edx            0x0 0
ebx            0x1 1

esp            0xbfbfecb0 0xbfbfecb0
ebp            0xbfbfecf8 0xbfbfecf8
esi            0xbfbfed40 -1077940928
edi            0x0 0

eip            0x8048309 0x8048309
eflags         0x246 582
cs             0x33 51
ss             0x3b 59

ds             0x3b 59
es             0x3b 59
fs             0x3b 59
gs             0x1b 27

(gdb) x/4 0xbfbfecb0

0xbfbfecb0: 0x00000003 0x28102000 0x00010000 0x00000000
(gdb) step          

[+] ICMP: 74.125.95.147 -> 74.125.95.147

52 break;
(gdb) x/4 0xbfbfecb0

0xbfbfecb0: 0x08062664 0x08066e98 0x08066e98 0x00000000
(gdb) printf "%s\n", 0x08062664

[+] ICMP: %s -> %s

 
(gdb) printf "%s\n", 0x08066e98

74.125.95.147
(gdb) x/4 0xbfbfecb0

0xbfbfecb0: 0x08062664 0x08066e98 0x08066e98 0x00000000
 

Como pueden ver después de ejecutar el step en la pila tenemos


(gdb) x/4 0xbfbfecb0
0xbfbfecb0: 0x08062664 0x08066e98 0x08066e98 0x00000000
La primera es la cadena de formato:

Código
(gdb) printf "%s\n", 0x08062664
[+] ICMP: %s -> %s

Y las 2 siguientes es la misma IP de Origen

Código
(gdb) printf "%s\n", 0x08066e98
74.125.95.147
 
en conclusión, el inet_ntoa o algo no esta funcionando bien Tiene un Bug!! Aun que este no es muy dañino.



Y en cambio como mencione en el post si lo ejecutamos desde 2 printf distintos eso no pasa, debido a que la dirección Estática se renueva, ¿Por que no se renueva cuando se mandan los 2 al mismo printf?


Comentarios

Entradas populares de este blog

Clave WPA2 por Defecto de equipos TotalPlay (Huawei HG8245H)

Cable modem Ubee - WPA2 y WPS por defecto