nbEasyTshark 01-04 从环境配置开始~

01 概述

基于tshark, cpp开发类wireshark软件 nbEasyTshark

Wireshark主要特点:

  • 支持三千多种协议深度解析
  • 实时捕获和离线分析
  • 强大的过滤功能 (Display Filter、Capture Filter)
  • 支持流分析(FollowStream)
  • 支持多种操作系统(Windows、Linux、macOS)
  1. tshark命令练习
    1. 使用 tshark -D 枚举你的网络接口。
    2. 选择合适的网卡接口并抓取1000个数据包(提示:使用 -c 1000 参数限制抓包数量),然后保存为capture.pcap。
    3. 解析 capture.pcap 并筛选出所有TCP协议的数据包。
    4. 统计 capture.pcap 中各个协议的数据包数量。

02 开发环境搭建

真的很久很久没开发windows端应用了。这次使用VisualStudio 2022为IDE开发,习惯了JB家的IDE和高颜值vscode,用这个old school的界面看着有点难受喵~

挂一个项目地址:https://github.com/yangnanbei/nb_easy_tshark

首先我们要读取tshark的内容。tshark工具可以在命令行下分析数据包,我们整点包先。

tshark -h一堆东西输出,toooo verbose,我直接不看,问一手AI先。

tshark -D

找网口:

那么显然 \Device\NPF_{FFCB4D95-E737-4DCA-B016-522C9BA641B5} 这就是我们要找的网口了

tshark制定网口留存1000个数据包:

tshark -i ‘\Device\NPF_{FFCB4D95-E737-4DCA-B016-522C9BA641B5}’ -c 1000 -w capture.pcap

注意反斜杠有需要转义,我们可以直接用单引号括起来先。

ok,拿到了对应的包。

Length Name

263324 capture.pcap

VisualStudio cmd编码问题

将tshark的输出通过popen传入Visual Studio,测试时发现了个问题。

那就是cmd的默认编码是gbk的,需要改成utf8才能愉快玩耍~

见以下攻略:

C++/8/VS2022更改为UTF-8的n种方法 – 归海言诺 – 博客园

但是博主的攻略有个问题是:

HKEY_LOCAL_MACHINE\Software\Microsoft\Command Processor

在右侧窗格中,右键单击空白区域,选择“新建”>“DWORD值(32位)”。

将新创建的DWORD值命名为“Autorun”,然后双击它以编辑其值数据。

在“数值数据”框中,输入“chcp 65001”,然后点击“确定”

这里“新建”>“DWORD值(32位)”是不对的,类型得是字符串类型

但是后续发现设置autorun会导致cmd/powershell启动报错

最后采用在main函数开头设置utf8属性

 setlocale(LC_ALL, "zh_CN.UTF-8"); 

03 以json格式获取数据包信息

我们通过tshark获取信息之后要将其存储下来,

信息结构体:

相关命令:

tshark -r .\10pkts.pcap -T fields -e frame.number -e frame.time -e ip.src -e ip.dst -e _ws.col.Protocol -e _ws.col.Info

解析离线包的相关数据:

typedef struct Packet_ {
    int frame_number;
    std::string time;
    std::string src_ip;
    std::string dst_ip;
    int src_port;
    int dst_port;
    std::string protocol;
    std::string info;
} Packet;

使用rapidjson库以json格式输出,解析成功:

04 pcap文件格式

我们已经可以读取离线pcap的一些元组信息。现在我们需要获取数据包的原始十六进制数据

那么将packet的数据保存在结构体中,在需要的时候去读吧。

packet文件格式

可以看到 pcap文件结构中,以一个24字节的Pcap Header开头,而后的每个包都以Packet Header+Packet Data的形式存在。

Pcap Header

全局文件头,共24B位于文件的起始位置,每个文件只有一个。包含如下字段

  1. magic number(4B): 用于标识文件格式
    1. 可以从此区分大端(0xa1b2c3d4)和小端(0x4dc3b2a1)
      • 现在电脑大部分是小端模式
  2. version(2B + 2B):pcap文件版本号,如2.4
    1. major(2B): 主要版本
    2. minor(2B): 次要版本
  3. this zone(4B): 时区偏移,通常为0
  4. sigfigs(4B): 时间戳精度,通常为0
  5. snaplen(4B): 捕获的数据表最大长度
  6. network(4B): 链路层类型,如以太网

Packet Header

每个数据表的metadata,共16B,包含如下字段:

  1. timestamp second(4B): 时间戳, 秒级
  2. timestamp microseconds(4B):时间戳,微妙级
  3. capture length(4B): 实际捕获的数据包长度。即抓取到的数据帧长度,由此可以得到下一个数据帧的位置。
  4. original length(4B): 数据包原始长度。离线数据长度,网路中实际数据帧的长度,一般不大于 Caplen,多数情况下和 Caplen值一样

数据表数据以16进制的形式存储。我们可以将其读取后以16进制形式打印出来

 /* read pcap data */
std::vector<unsigned char> data(packetHeader.caplen);
file.read(reinterpret_cast<char*>(data.data()), packetHeader.caplen);

按照之前所说,我们现在要记录报文的偏移和长度,把它保存起来,那就需要

  1. 修改一下packet的结构体。
  2. tshark在分析的时候,将报文的长度输出出来: frame.cap_len. 这样我们就能获取报文长度,来计算偏移并记录了。

在解析的时候记录每个包的offset+caplen,而后在最后读取文件时输出即可。

解析函数:

bool readPacketHex(const std::string& packet_file, uint32_t file_offset,
                   uint32_t length, std::vector<unsigned char>& buffer)
{
    buffer.resize(length);
    FILE* file = fopen(packet_file.c_str(), "rb");
    if (!file) {
        std::cerr << "Failed to open file: " << packet_file << std::endl;
        buffer.clear();
        return false;
    }
    if (fseek(file, file_offset, SEEK_SET) != 0) {
        std::cerr << "Failed to seek to offset: " << file_offset << std::endl;
        fclose(file);
        buffer.clear();
        return false;
    }
    size_t bytesRead = fread(buffer.data(), 1, length, file);
    fclose(file);
    if (bytesRead != length) {
        std::cerr << "Failed to read data from file. Expected: " << length << ", got: " << bytesRead << std::endl;
        buffer.resize(bytesRead);
        return false;
    }
    return true;
}

此时我们的相关定义如下:

struct PcapHeader {
    uint32_t magic_number;
    uint16_t version_major;
    uint16_t version_minor;
    int32_t  thiszone;
    uint32_t sigfigs;
    uint32_t snaplen;
    uint32_t network;
};

struct PacketHeader {
    uint32_t ts_sec;
    uint32_t ts_usec;
    uint32_t caplen;
    uint32_t len;
};

struct Packet {
    int frame_number;
    std::string time;
    uint32_t cap_len;
    std::string src_ip;
    uint16_t src_port;
    std::string dst_ip;
    uint16_t dst_port;
    std::string protocol;
    std::string info;
    uint32_t file_offset;
};

测试:

试一试我们解析出的hex数据和wireshark中做比较:

我们解析的:

wireshark中:

是能对应上的~

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇