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:
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) x/4 0xbfbfecb0
0xbfbfecb0: 0x08062664 0x08066e98 0x08066e98 0x00000000
La primera es la cadena de formato:
[+] ICMP: %s -> %s
Y las 2 siguientes es la misma IP de Origen
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?
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
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", 0x08066e9874.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