Today my friend Mario Diaz have discovered a interesting flaw in hping3, is a race condition + heap overflow dodgy of reproduce.
I love this kind of flaws, let's analyse the problem in order to make the exploit:
pcap_close sometimes cause a double free corruption:
pcap_next(0x8079f20, 0x8069c70, 130, 0, 0) = 0x807a12a
memcpy(0xb33e7970, "", 66) = 0xb33e7970
pcap_next(0x8079f20, 0x8069c70, 66, 0, 0) = 0x807a12a
memcpy(0xb33e7970, "", 66) = 0xb33e7970
pcap_next(0x8079f20, 0x8069c70, 66, 0, 0) = 0x807a12a
memcpy(0xb33e7970, "\252", 130) = 0xb33e7970
pcap_next(0x8079f20, 0x8069c70, 130, 0, 0) = 0x807a12a
--- SIGALRM (Alarm clock) ---
pcap_close(0x8079f20, 0, 0, 0x804eb0d, 0) = 505
When hping sends a packet, if you have specified the -c flag (number of packets) and all packets are sended, a sigalarm is called:
send.c:void send_packet (int signal_id) {
...
sent_pkt++;
Signal(SIGALRM, send_packet);
if (count != -1 && count == sent_pkt) { /* count reached? */
Signal(SIGALRM, print_statistics);
alarm(COUNTREACHED_TIMEOUT);
hping2.h:#define COUNTREACHED_TIMEOUT 1
One second later, a sigalarm is triggered, and print_statistics is called.
statistics.c:print_statistics(int signal_id) {
close_pcap();
I have reproduced the problem:
# ./pcap
*** glibc detected *** double free or corruption (out): 0x0804adc0 ***
Abortado
# ldd -d pcap
linux-gate.so.1 => (0xffffe000)
libpcap.so.0.8 => /usr/lib/libpcap.so.0.8 (0xb7f94000)
libc.so.6 => /lib/tls/i686/cmov/libc.so.6 (0xb7e63000)
/lib/ld-linux.so.2 (0xb7fd5000)
When the race condition succeed, the pcap_close() is called twice, and then the double-free happens.
I love this kind of flaws, let's analyse the problem in order to make the exploit:
pcap_close sometimes cause a double free corruption:
pcap_next(0x8079f20, 0x8069c70, 130, 0, 0) = 0x807a12a
memcpy(0xb33e7970, "", 66) = 0xb33e7970
pcap_next(0x8079f20, 0x8069c70, 66, 0, 0) = 0x807a12a
memcpy(0xb33e7970, "", 66) = 0xb33e7970
pcap_next(0x8079f20, 0x8069c70, 66, 0, 0) = 0x807a12a
memcpy(0xb33e7970, "\252", 130) = 0xb33e7970
pcap_next(0x8079f20, 0x8069c70, 130, 0, 0) = 0x807a12a
--- SIGALRM (Alarm clock) ---
pcap_close(0x8079f20, 0, 0, 0x804eb0d, 0) = 505
When hping sends a packet, if you have specified the -c flag (number of packets) and all packets are sended, a sigalarm is called:
send.c:void send_packet (int signal_id) {
...
sent_pkt++;
Signal(SIGALRM, send_packet);
if (count != -1 && count == sent_pkt) { /* count reached? */
Signal(SIGALRM, print_statistics);
alarm(COUNTREACHED_TIMEOUT);
hping2.h:#define COUNTREACHED_TIMEOUT 1
One second later, a sigalarm is triggered, and print_statistics is called.
statistics.c:print_statistics(int signal_id) {
close_pcap();
I have reproduced the problem:
#include <pcap.h>
#include <stdio.h>
int main (void) {
pcap_t *p;
char *errbuf = (char *)malloc(3000);
if (p = pcap_open_live(NULL,65535,1,3000,errbuf)) {
pcap_close(p);
pcap_close(p);
} else {
printf("open failed\n");
}
}
# ./pcap
*** glibc detected *** double free or corruption (out): 0x0804adc0 ***
Abortado
# ldd -d pcap
linux-gate.so.1 => (0xffffe000)
libpcap.so.0.8 => /usr/lib/libpcap.so.0.8 (0xb7f94000)
libc.so.6 => /lib/tls/i686/cmov/libc.so.6 (0xb7e63000)
/lib/ld-linux.so.2 (0xb7fd5000)
When the race condition succeed, the pcap_close() is called twice, and then the double-free happens.
Comentarios
mañana por la noche me lo leo, me iba a dormir ya :P