2012-01-12 2 views
0

Я пытаюсь извлечь TCP полезной нагрузки из пакета, а вот минимальный случай захвата обратного вызова:Tcp извлечение полезной нагрузки и правильный IP-адрес

void capture_callback (u_char *hdr , const struct pcap_pkthdr* pkthdr , const u_char* buff) 
{ 
    struct ether_header *eptr = (struct ether_header *) buff; 
    buff += sizeof (ether_header); /* jump over ethernet header: 14 bytes */ 

    if (ntohs (eptr->ether_type) == ETHERTYPE_IP) 
    { 
     struct ip *iph; 
     struct tcphdr *tcp_header; 

     iph = (struct ip *) buff; 
     buff += sizeof (ip); /* jump over ip header */ 

     if (iph->ip_p == IPPROTO_TCP) 
     { 
      tcp_header = (struct tcphdr *) buff; 
      buff += sizeof (tcphdr); /* jump over tcp header */ 

      cout << inet_ntoa (iph->ip_src) << ":" << ntohs (tcp_header->th_sport) << 
         " --> " << inet_ntoa(iph->ip_dst) << ":" << ntohs (tcp_header->th_dport) << endl; 

     } 

    } 
} 
  1. Но что-то пошло не так здесь, источник и место назначения IP-адрес тот же.

  2. И кроме того, как я могу распечатать полезную нагрузку? Поскольку я не могу просто преобразовать массив unsigned char в массив символов явно, который заканчивается на «\ 0», это может привести к ошибке.

    192.168.56.1:48065 -> 192.168.56.1:80

    192.168.56.80:80 -> 192.168.56.80:48065

EDIT

- --------------------

Чинк к Celeda, я решил проблему с ip-адресом, отделив вызов ine t_ntoa:

cout << "IP: " << inet_ntoa (iph->ip_src) << ":" << ntohs (tcp_header->th_sport) << 
       " --> "; 
    cout << inet_ntoa(iph->ip_dst) << ":" << ntohs (tcp_header->th_dport) << endl; 

А теперь вторая часть, я использую:

cout << hex << buff << endl;

Для протокола HTTP, и я что-нибудь вроде "GET /", но многократная пустой строки не вижу

РЕДАКТИРОВАТЬ 2

--------------------------

Я пока не так уверен в настройках TCP, я проверю больше документов о деталях, , но пока это хорошо работает.

if (iph->ip_p == IPPROTO_TCP) 
    { 
     tcp_header = (struct tcphdr *) buff; 
     buff += tcp_header->th_off * 4; 

     cout << "IP: " << inet_ntoa (iph->ip_src) << ":" << ntohs (tcp_header->th_sport) << 
        " --> "; 
     cout << inet_ntoa(iph->ip_dst) << ":" << ntohs (tcp_header->th_dport) << endl; 

     for (int i = 0 ; i < iph->ip_len - iph->ip_off * 4; i ++) 
     { 
      if (isascii (buff[i])) 
      { 
       cout << buff[i]; 
      } 
     } 
     cout << endl << "-----------" << endl; 

    } 
+0

Для второй части, я не уверен, может быть, 'buff' не совсем указывает на нужное место. Я вижу, что вы делаете 'buff + = sizeof (tcphdr)', но, возможно, есть опции TCP, которые вам нужно пропустить. Я также не знаю C++, поэтому я не уверен, что на самом деле делает 'hex << buff'. Тем не менее, я подозреваю, что он ожидает строку с нулевым завершением; Я думаю, вам нужно использовать некоторую функцию, которая принимает длину в качестве входных данных, чтобы она не выходила за пределы пакета. – Celada

+0

@Celada см. «Редактировать 2» – daisy

ответ

1
  1. inet_ntoa() использует статический буфер. Вы переписываете буфер, вызывая его дважды. Вместо этого используйте inet_ntop().

  2. Полезная нагрузка может быть двоичной. Как вы хотите распечатать его? Как гексагон или что-то в этом роде? Просто просмотрите полезную нагрузку и напечатайте байты как шестую по одному для упрощенного шестнадцатеричного дампа. Или, если вы уверены, что это пригодные для печати данные, вы можете отправить их непосредственно на выход с помощью любой функции, такой как fwrite(), которая позволяет указать длину строки для записи.

РЕДАКТИРОВАТЬ ДОПОЛНИТЕЛЬНУЮ ИНФОРМАЦИЮ В ВОПРОСЕ

«Лишние символы» вы видите перед звуком HTTP данных, таких как параметры TCP вы пытаетесь интерпретировать как данные полезную нагрузку. Не забудьте правильно рассчитать размер заголовка TCP, когда вы переместите указатель buff над ним. Это 4 байта * th_off.Пока вы на нем, вы должны сделать то же самое для IP-заголовка, используя ip_hl, потому что заголовок IP не всегда равен 20 байтам.

После этого конечное условие в вашей петле for неверно. Сначала ip_off (смещение фрагмента) не входит в него, а во-вторых, и ip_hl, и tcp_off измеряются в единицах 4 байта, а не в байтах.

Сравните то, что вы получаете с кодом, с тем, как Wireshark декодирует один и тот же пакет, и вы сможете легко диагностировать любое дальнейшее несоответствие.

+0

См. Мое обновление, спасибо! – daisy

Смежные вопросы