2015-04-30 7 views
1

КонтекстПечать «showname» атрибут поля в tshark

У меня есть файл, содержащий PCAP кучу кадров радиомаяка (другими словами, я кладу адаптер Wi-Fi в режиме монитора, начал захватывать при фильтрации по «wlan.fc.type_subtype == 0x08» и сохранил это).

Теперь я хочу, как-то, отобразить определенные поля этих пакетов. Среди прочего:

  • SSID (wlan_mgt.ssid)
  • MAC (wlan.ta)
  • Текущий канал (wlan_mgt.ds.current_channel)
  • Группа Cipher (wlan_mgt.rsn.gcs.type)
  • попарных шифры (wlan_mgt.rsn.pcs.type)
  • Authentication Люкс (wlan_mgt.rsn.akms.type)

Я не очень забочусь о представлении: простой текст, xml, json, csv, X. Я в порядке с ним. Я просто не хочу больше данных, чем мне действительно нужно, и выход должен быть значимым для человеческого (wirehark newb) глаза.

В конце концов, я также хочу отфильтровать pcap, чтобы получить уникальный набор и подсчитать вхождения (некоторые «сортировать | uniq -c» будут делать), но давайте не будем туда пока.

Мое решение до сих пор

Первым шагом может быть, например:

$ tshark -r capture.pcap -c 1 -T fields -e wlan_mgt.ssid -e wlan.ta -e wlan_mgt.ds.current_channel -e wlan_mgt.rsn.gcs.type -e wlan_mgt.rsn.pcs.type -e wlan_mgt.rsn.akms.type 
MySSID XX:XX:XX:XX:XX:XX 2 4 4 2 

После (вручную) соответствие число их текстуального значения, вы получите это:

  • SSID = MySSID
  • MAC (wlan.ta) = XX: XX: XX: XX: XX: XX
  • Текущий канал = 2
  • тип
  • Группа Cipher = Группа Cipher Suite: AES (CCM) (4)
  • типа попарных шифры = парный Cipher Suite: AES (CCM) (4)
  • Authentication Люкс = Auth Key Руководство (AKM): PSK (2)

Это то, что я ищу. Но, как сказано, я должен сделать это вручную, что не является вариантом.

Вопрос

Вы можете увидеть мой текущий подход к указанной цели. Делая

tshark -r capture.pcap -c 1 -T pdml 

я, например (рубильник):

<field name="wlan_mgt.rsn.pcs.list" showname="Pairwise Cipher Suite List 00-0f-ac (Ieee8021) AES (CCM)" size="4" pos="112" show="" value=""> 
    <field name="wlan_mgt.rsn.pcs" showname="Pairwise Cipher Suite: 00-0f-ac (Ieee8021) AES (CCM)" size="4" pos="112" show="1027076" value="000fac04"> 
     <field name="wlan_mgt.rsn.pcs.oui" showname="Pairwise Cipher Suite OUI: 00-0f-ac (Ieee8021)" size="3" pos="112" show="4012" value="000fac"/> 
     <field name="wlan_mgt.rsn.pcs.type" showname="Pairwise Cipher Suite type: AES (CCM) (4)" size="1" pos="115" show="4" value="04"/> 
    </field> 
</field> 

..., который говорит мне, что tshark имеет информацию, что нужно (в виде «showname» атрибут).

По-видимому, при работе с полями «-T -e X» tshark выводит значение, указанное в атрибуте «show». Я чувствую, что хочу, что за атрибутом «показанный». К сожалению, после раздражающего Google для в то время как я до сих пор не знаю, как и если это возможно.

Я также открыт для радикально разных идей, но основной вывод заключается в том, что я не могу расстаться с файлом pcap (который исключает iwlist , kismet и т. д.) Я также предпочтительно не начинаю писать правила поиска и замены, чтобы заменить бессмысленные цифры их текстовым представлением. Надеюсь решить его более чистым способом.

ответ

1

Я продолжал возиться с tshark некоторое время, пока я не решил при этом не может быть сделано. Немного программирования с использованием потрясающей библиотеки C++ libtins доставил меня туда, где я должен был быть.

Источник внизу. Наслаждайтесь :)

#include <tins/tins.h> 

#include <algorithm> 
#include <iostream> 
#include <map> 
#include <string> 

using namespace Tins; 
using namespace std; 


/* 
* Container class for the data that is retrieved from the beacon. 
*/ 
class Unit { 
public: 
    /* 
    * Constructor. Parses the Dot11Beacon object and takes all the necessary 
    * data from it. 
    */ 
    Unit(Dot11Beacon& beacon); 
    Unit() = default; 
    unsigned getCount(); 
    void incrementCount(); 

    /* 
    * Prints this object onto the command line, in CSV format 
    */ 
    void print(); 

private: 
    string ssid; 
    string bssid; 
    unsigned channel; 
    unsigned count; 

    string gcs; // Group Cipher Suite 
    string pcs; // Pairwise Cipher Suite 
    string akm; // Authentication suite 

    /* 
    * Returns a string representation of a RSNInformation::CypherSuites enum value 
    */ 
    string type_to_string(const RSNInformation::CypherSuites& type); 

    /* 
    * Returns a string representation of a RSNInformation::AKMSuites enum value 
    */ 
    string type_to_string(const RSNInformation::AKMSuites& type); 
}; 

Unit::Unit(Dot11Beacon& beacon) : 
    count {1} /* When this unit is created, it has been seen exactly once */ { 
    ssid = beacon.ssid(); 
    bssid = beacon.addr3().to_string(); 
    channel = unsigned(beacon.ds_parameter_set()); 

    RSNInformation rsn; 
    for(const auto &opt : beacon.options()) { 
     if (opt.option() == Dot11::RSN) { 
      rsn = beacon.rsn_information(); 

      // Put all authentication suite types in a string 
      const RSNInformation::akm_type& akmTypeList = rsn.akm_cyphers(); 
      for (const auto& akmIt : akmTypeList) { 
       if (akm.size() == 0) 
        akm += type_to_string(akmIt); 
       else 
        akm += ";" + type_to_string(akmIt); 
      } 

      // Put all group cipher types in a string 
      const RSNInformation::CypherSuites& gcsType = rsn.group_suite(); 
      gcs = type_to_string(gcsType); 


      // Put all pairwise ciphers in a string 
      const RSNInformation::cyphers_type& pcsTypeList = rsn.pairwise_cyphers(); 
      for (const auto& pcsIt : pcsTypeList) { 
       if (pcs.size() == 0) 
        pcs += type_to_string(pcsIt); 
       else 
        pcs += ";" + type_to_string(pcsIt); 
      } 
     } 
    } 
} 

unsigned Unit::getCount() { 
    return count; 
} 

void Unit::incrementCount() { 
    count += 1; 
} 

void Unit::print() { 
    string ssid_to_print; 
    if (ssid.length() == 0) { 
     ssid_to_print = "<ZERO_LENGTH>"; 
    } else if (!isprint(ssid[0])) { 
     ssid_to_print = to_string(static_cast<int>(ssid[0])); 
    } else { 
     ssid_to_print = ssid; 
    } 
    if (find(ssid_to_print.begin(), ssid_to_print.end(), ',') != ssid_to_print.end()) { 
     ssid_to_print = "\"" + ssid_to_print + "\""; 
    } 
    cout << ssid_to_print << "," 
     << bssid << "," 
     << to_string(channel) << "," 
     << to_string(count) << "," 
     << gcs << "," 
     << pcs << "," 
     << akm << endl; 
} 

string Unit::type_to_string(const RSNInformation::CypherSuites& type) { 
    switch (type) { 
    case RSNInformation::CypherSuites::CCMP: 
     return "CCMP"; 
     break; 
    case RSNInformation::CypherSuites::TKIP: 
     return "TKIP"; 
     break; 
    case RSNInformation::CypherSuites::WEP_104: 
     return "WEP_104"; 
     break; 
    case RSNInformation::CypherSuites::WEP_40: 
     return "WEP_40"; 
     break; 
    } 
} 

string Unit::type_to_string(const RSNInformation::AKMSuites& type) { 
    switch (type) { 
    case RSNInformation::AKMSuites::PMKSA: 
     return "PMKSA"; 
     break; 
    case RSNInformation::AKMSuites::PSK: 
     return "PSK"; 
     break; 
    } 
} 

/* 
* Class that reads the pcap, keeps track of the units and writes out one 
* beacon frame in pcap format for each unique AP it finds. This file is called 
* "unique_beacons.pcap" 
*/ 
class PCAPParser { 
public: 
    /* 
    * Constructor. It takes the exact parameters that it will pas on to its 
    * FileSniffer object (a FileSniffer is actually just a file reader). 
    */ 
    PCAPParser(const string& pcapFilename, const string& filter); 

    /* 
    * Start reading the file. 
    */ 
    bool run(); 

    /* 
    * Print CSV header and ask all of our collected Unit objects to print themselves 
    */ 
    void print(); 

private: 
    FileSniffer sniffer; 
    PacketWriter writer; 
    map<string, Unit> apMap; // stands for Access Point Map 

    bool handler(PDU&); 
}; 

PCAPParser::PCAPParser(const string& pcapFilename, const string& filter) : 
    sniffer {pcapFilename, filter}, 
    writer {"unique_beacons.pcap", PacketWriter::RADIOTAP} { 
    for (auto it = apMap.begin(); it != apMap.end(); it++) { 
     it->second.print(); 
    } 
} 

bool PCAPParser::run() { 
    sniffer.sniff_loop([this] (PDU& pdu) { return (bool) this->handler (pdu); }); 
    return true; 
} 

bool PCAPParser::handler(PDU& pdu) { 
    Dot11Beacon& beacon = pdu.rfind_pdu<Dot11Beacon>(); 

    // An ESSID may span multiple BSSID's. Also, it's nice to keep track of what 
    // channels an AP has been on. Therefore, the combination of SSID, BSSID and 
    // channel is considered key. 
    const string& ssid = beacon.ssid(); 
    const string& mac = beacon.addr3().to_string(); 
    const unsigned channel = unsigned(beacon.ds_parameter_set()); 
    const string key = ssid + mac + to_string(channel); 
    if (apMap.find(key) == apMap.end()) { // we've got a new one 
     Unit unit(beacon); 
     apMap[key] = unit; 
     writer.write(pdu); 
    } else { 
     apMap[key].incrementCount(); 
    } 
    return true; 
} 

void PCAPParser::print() { 
    // Print the headers for the CSV output 
    cout << "SSID,BSSID,Current_channel,Count,Group_Cipher,Pairwise_Ciphers,Authentication_Suite" << endl; 

    // Ask each of the units to print themselves for the CSV output 
    for (auto it = apMap.begin(); it != apMap.end(); it++) { 
     it->second.print(); 
    } 
} 

int main(int argc, char *argv[]) { 
    if(argc != 2) { 
     std::cout << "Usage: " << *argv << " <PCAP_FILE>\n"; 
     return 1; 
    } 

    PCAPParser pcapParser(argv[1], "wlan type mgt subtype beacon"); 
    pcapParser.run(); 
    pcapParser.print(); 
} 

Compile с:

g++ pcapreader.cpp -o pcapreader -O3 -std=c++11 -lpthread -ltins 

Выход:

$ ./pcapreader capture.pcap 
SSID,BSSID,Current_channel,Count,Group_Cipher, Pairwise_Ciphers,Authentication_Suite 
MyWiFi,XX:XX:XX:XX:XX:XX,13,2,TKIP,TKIP;CCMP,PSK 
... 
... 

Конечная нота: если открыть unique_beacons.pcap, вы можете найти много [Malformed Packet]. По-видимому, кадр все еще может быть успешно проанализирован, если некоторые из отмеченных параметров получены неверно. Вы можете попробовать изменить код, чтобы он только записывал кадры в полностью закрытый файл pcap.