2014-12-04 14 views
5

Sto tentando di analizzare un pacchetto TCP e quindi assegnarlo a un puntatore all'inizio del payload.Analisi di un pacchetto TCP dati

Sto usando C e questo è il mio codice finora:

void dump(const unsigned char *data, int length) { //*data contains the raw packet data 
    unsigned int i; 
    static unsigned long pcount = 0; 

    // Decode Packet Header 
    struct ether_header *eth_header = (struct ether_header *) data; 

    printf("\n\n === PACKET %ld HEADER ===\n", pcount); 

    printf("\nSource MAC: "); 
    for (i = 0; i < 6; ++i) { 
     printf("%02x", eth_header->ether_shost[i]); //? Why don't i use nthos here? 
     if (i < 5) printf(":"); 
    } 

    unsigned short ethernet_type = ntohs(eth_header->ether_type); 
    printf("\nType: %hu\n", ethernet_type); 

    if (ethernet_type == ETHERTYPE_IP) { //IP Header 
     printf("\n == IP HEADER ==\n"); 
     struct ip *ip_hdr = (struct ip*) data + sizeof(struct ether_header); 
     unsigned int size_ip = ip_hdr->ip_hl * 4; 
     printf("\nIP Version: %u", ip_hdr->ip_v); //? Nthos or no nthos 
     printf("\nHeader Length: %u", ip_hdr->ip_hl); //? Nthos or no nthos 
     printf("\nTotal Length: %hu", ntohs(ip_hdr->ip_len)); //? Nthos or no nthos 

     // TCP Header 
     printf("\n== TCP HEADER ==\n"); 
     struct tcphdr *tcp_hdr = (struct tcphdr*) data + sizeof(struct ether_header) + size_ip; 
     printf("\n Source Port: %" PRIu16, nthos(tcp_hdr->th_sport)); 
     printf("\n Destination Port: %" PRIu16, nthos(tcp_hdr->th_dport)); 
     printf("\n fin: %" PRIu16, tcp_hdr->fin); 
     printf("\n urg: %" PRIu16, tcp_hdr->urg); 
     printf("\n ack_seq: %" PRIu32, ntohl(tcp_hdr->ack_seq)); 

     //Transport payload! i.e. rest of the data 
     const unsigned char *payload = data + ETH_HLEN + size_ip + sizeof(struct tcphdr) + tcp_hdr->doff; 

    } 

Sono sicuro che ci sono errori in questo codice, perché i numeri di porta sono tutti strani. Non una singola assegna a 80. Anche la versione Ip prodotta può essere davvero strana (come la versione 11). Che cosa sto facendo di sbagliato? Grazie!

Inoltre, non sono sicuro quando utilizzare nthos e quando non farlo. So che nthos è per interi senza segno a 16 bit e so che nthol è per interi senza segno a 32 bit, ma sono consapevole del fatto che non si intende usarli per tutto in quei pacchetti (come: tcp_hdr-> fin). Perché certe cose e non loro?

MOLTE GRAZIE!

EDIT:

Grazie arte per fissare la maggior parte dei problemi f. Ho modificato il mio tcp_hdr e ip_hdr così le parentesi ora sono corrette!

ho ancora 2 problemi:

  • I primi 10 byte del payload ha strani simboli (quindi penso che non ho assegnato correttamente il carico utile).
  • Non sono ancora sicuro quando utilizzare nthos/nthol. So che u_int16_t è ntohs e u_int32_t è ntohl. Ma per quanto riguarda le cose che sono firmate int o non abbreviate int. Ad esempio non ho usato ntohs o nthol per ip_v perché funzioni. Perchè no? "Ip_hdr-> ip_hl" nthol? ecc ...

EDIT2

Ho fissato perché il mio carico non è stato correttamente l'output (è perché ho calcolato la dimensione TCP_header sbagliato).

Anche se sono ancora confuso su quando utilizzare nthos, lo metto come una domanda a parte, perché penso di aver posto troppe domande su questo post!

When to use ntohs and ntohl in C?

+0

Lo sai che le cose come numeri di porta sono in * network ordine * di byte? Usa 'ntohs' per convertire un valore breve (16 bit) dall'ordine dei byte di rete all'ordine dei byte host. –

+0

Ho provato entrambi, ma ho preso numeri strani per eitehr. Aggiornamento del codice ora comunque! –

+0

Ci sono altri campi che sembrano corretti? Come gli indirizzi di origine/destinazione? L'intestazione ethernet? Come appare rispetto allo stesso pacchetto, ad es. Wireshark? E tu * lo * lo ricevi su un socket raw? E ricevere * tutto * del pacchetto? –

risposta

5

Molto probabilmente il problema è qui:

struct ip *ip_hdr = (struct ip*) data + sizeof(struct ether_header); 
struct tcphdr *tcp_hdr = (struct tcphdr*) data + sizeof(struct ether_header) + size_ip; 

Facendo (struct ip*) data + sizeof(struct ether_header) primi dati calchi di struct ip *, poi aggiunge sizeof(struct ether_header) ad esso, che conosciamo dalla aritmetica puntatore non farà quello che ci si aspetta fare.

Se il problema è ancora chiaro, ecco un semplice programma che dovrebbe puntare nella giusta direzione:

#include <stdio.h> 

struct foo { 
    int a, b; 
}; 

int 
main(int argc, char **argv) 
{ 
    char *x = NULL; 

    printf("%p\n", x); 
    printf("%p\n", (struct foo *)x + 4); 
    printf("%p\n", (struct foo *)(x + 4)); 

    return 0; 
} 
+0

Questo è stato risolto come quasi tutti i miei problemi. Ti dispiace se rispondi anche alla seconda parte della mia domanda come quando usare ntohs. La mia regola corrente che ho inventato è per qualsiasi cosa di tipo u_int16_t è ntohs e u_int32_t è ntohl. Ma per quanto riguarda le cose che sono firmate int o non abbreviate int. Ad esempio, non ho usato ntohs per ip_v perché funzioni. Perchè no? Grazie –

+0

Guarda l'intestazione IP e una definizione. La regola di base è: non si convertono i valori 1B o inferiore (ip_v, ip_hl). Si utilizzano ntohs per i valori 2B (ip_len, ip_p). Usa ntohl per valori 4B. "Ma per quanto riguarda le cose che sono firmate int o non abbreviate int": Non importa se è firmato o meno (e non penso che ci siano valori firmati in ip hdr), così int firmato è solo un valore di 4B e corto senza segno è il valore 2B. Puoi vedere l'intestazione IP qui: http://en.wikipedia.org/wiki/IPv4#Header – davak

+0

quindi aspetta "ip_hdr-> ip_hl" usa htol allora dato che è di tipo "unsigned int ip_hl: 4;" Quando ho aggiunto htol, il programma termina prima ancora di leggere l'intestazione TCP (probabilmente significa che sta leggendo una parte della memoria che non dovrebbe). Comunque quando l'ho lasciato senza ntohl o ntohs ha funzionato bene! –

Problemi correlati