Pig(可理解为 Packet(数据包) intruder(入侵者) generator(生成器))是一个 Linux 数据包构造工具。
你可以用 Pig 测试你的 IDS/IPS 以及其他东西。
Pig 内置了大量已知的攻击特征签名可直接使用,你还可以根据自身需求扩展这个集合,
加入更具体的内容。
截至目前,它可以创建基于 TCP、UDP 和 ICMP 传输层的 IPv4 签名。
你也可以创建基于 ARP 协议的签名,甚至从 Ethernet 帧开始构建整个数据包。
如果你是通过我在 2600 2016 年春季 期刊 的文章来到这里,
请继续阅读以下文档章节,因为这只小 Pig 从那以后一直在进化。
非常简单:
[email protected]:~/src# git clone https://github.com/rafael-santiago/pig pig
[email protected]:~/src# cd pig
[email protected]:~/src/pig# git submodule update --init
你需要使用 Hefesto 来构建 pig。按照步骤让 Hefesto 在你的系统上正常工作后,进入 pig 的 src 子目录并运行以下命令:
[email protected]:~/src/pig/src# hefesto
执行后,你应该能在 src/bin 路径下找到 pig 二进制文件。你可以从 src/bin 相对路径使用它,或者 安装它。
如果构建时遇到问题,建议阅读 BUILD.md 中的一些备注。
安装时,你需要进入 src 子目录,然后调用:
[email protected]:~/src/pig/src# hefesto --install
卸载时,同样在 src 子目录下调用:
[email protected]:~/src/pig/src# hefesto --uninstall
Pigsty 文件 是纯文本文件,你可以在其中定义一组数据包签名。需要遵循特定的语法。下面是一个 pigsty 文件的示例:
[ signature = "Hello",
ip.version = 4,
ip.ihl = 5,
ip.tos = 0,
ip.src = 192.30.70.10,
ip.dst = 192.30.70.3,
ip.protocol = 17,
udp.dst = 1008,
udp.src = 32000,
udp.payload = "Hello!!" ]
基本上,所有签名数据必须放在方括号 [ ... ] 内。
在这个区域内,信息通过 域 = 数据 的模式提供。
如果你有一些计算机网络经验,表 1 中列出的大部分字段对你来说应该很熟悉。你需要使用这些字段来创建后续的签名。
表 1:pig 签名字段。
创建签名时,你不需要指定所有数据。如果只指定最相关的数据包部分,剩余部分将用默认值填充。校验和 始终 会被重新计算。
提示:查看子目录 pigsty。你会找到大量签名文件,并且会发现定义新的签名非常简单。
是的,这是可能的。要使用此功能,你只需在 IP 地址 类型的字段中填写表 2 中列出的值。
表 2:按地理区域的 IP。
| 要使用的值 | 含义 |
|---|
你可以在任何 IP 地址 类型的字段中使用 user-defined-ip 作为值。在这种情况下,你需要使用命令行选项 --targets。参见 使用 pig 部分了解更多信息。
如果你创建了你认为除了自身环境之外也具有相关性的 pigsty 文件,请提交 pull request 以便将这些有用的文件包含进来。提前感谢!
Pig 的使用非常直接,需要提供四个基本选项:
--signatures--gateway--net-mask--lo-iface你想了解更多每个选项的细节吧?……那就来吧:
--signatures 接收一个文件路径列表,指向 pigsty 文件。--gateway 用于指定网关地址。请注意 pig 会生成或至少尝试生成 ethernet 帧。因此,网关地址对于正确组合 层-1 数据非常重要。--net-mask 用于路由问题,需指定你的网络掩码。--lo-iface 用于告知你将要用来"排出"生成数据包的本机网络接口名称。--no-gateway 表示任何数据包都不会发送到网络外部。假设我们想要生成基于 DDos 的流量:
[email protected]:~# pig --signatures=pigsty/ddos.pigsty\
> --gateway=10.0.2.2\
> --net-mask=255.255.255.0 --lo-iface=eth0
现在我们想搞乱一切:
[email protected]:~# pig --signatures=pigsty/ddos.pigsty,pigsty/attackresponses.pigsty,\
> pigsty/badtraffic.pigsty,pigsty/backdoors.pigsty\
> --gateway=10.0.2.2 --net-mask=255.255.255.0 --lo-iface=eth0
使用选项 --timeout=<毫秒数>
使用 --no-echo 选项。
使用 --targets 选项。你可以指定一个基于精确 IP、IP 掩码和 CIDR 的列表。
看这个例子:
[email protected]:~# pig --signatures=pigsty/local-mess.pigsty\
> --targets=192.30.70.3,192.30.70.*,192.30.70.0/9\
> --gateway=10.0.2.2\
> --net-mask=255.255.255.0\
> --lo-iface=eth0
当加载的签名不会将数据发送到当前网络之外时,这很有用。要标记此情况,你需要使用选项 --no-gateway。当使用 --no-gateway 选项时,你不需要指定网关地址,因为数据包不会流出当前网段。因此,告知网络掩码也变得无关紧要。
例如:
[email protected]:~# pig --signatures=pigsty/local_traffic.pigsty --no-gateway --lo-iface=eth2
在上面的示例中,以太网帧将不再是 pig 的责任。因此,pig 不会抱怨缺少 --gateway 和 --net-mask 选项。
当你需要生成 ARP 流量时,--no-gateway 选项非常方便。请查看另一份说明文档,了解如何使用 pig 执行 ARP 欺骗。
有时你可能只需要发送一个签名,然后返回到调用方以检查之后发生了什么。当你将此应用程序用于 系统测试 或 单元测试 的支持时,这种需求很常见。因此,如果你需要这样做,可以尝试使用 --single-test 选项:
[email protected]:~# pig --signature=pigsty/syn-scan.pigsty --targets=127.0.0.1 --single-test\
> --gateway=10.0.2.2 --net-mask=255.255.255.0 --lo-iface=eth0
执行此命令后,pig 将从文件 syn-scan.pigsty 中只选择一个签名,尝试发送它然后退出。如果过程中发生错误,pig 将以 退出码 为 1 退出;否则 pig 将以 退出码 为 0 退出。
pig 的基本操作模式是一个无尽的循环,它按照之前定义的超时向网络喷射大量数据包。
你可以使用选项 --loop=<模式> 来定义 pig 如何遍历加载的数据包进行发送。目前有两种模式:random(默认)和 sequential。
sequential 模式在到达加载的数据包签名列表末尾时会重新迭代这些签名。
子任务是一些与数据包构造相关的有用的小型任务,它们内置于 pig 中,可帮助你进行构造会话。这些任务可以通过选项 --sub-task=<任务名> 访问。
由于子任务实际上是子程序,它们有自己的特性,因此详细说明见各自的独立手册。请参考表 3 以了解详情。
表 3:pig 子任务。
到目前为止,你可以构建基于 IPv4 且传输层为 UDP 或 TCP 的数据包。你也可以构建 ARP 数据包。
然而,你仍然可以从 Ethernet 帧开始构建数据包。这样做的好处是可以在 Ethernet 负载之上几乎构建任何东西。
例如,即使 pig 目前不提供对烹饪好的 IPv6 构建的支持,你仍然可以使用基于原始 Ethernet 的 pigsty 来构建它。看:
[ eth.hwdst = "5C:AC:4C:AA:F5:B5",
eth.hwsrc = "08:95:2A:AD:D6:4F",
eth.type = 0x86DD,
eth.payload = "\x60\x00\x00\x00\x00\x20\x3a\xff\xfe\x80\x00\x00\x00\x00\x00\x00\x0a\x95\x2a\xff\xfe\xad\xd6\x4f\xfe\x80\x00\x00\x00\x00\x00\x00\x55\x51\x00\xc2\x18\x0f\xdb\x46\x88\x00\x32\x01\xe0\x00\x00\x00\xfe\x80\x00\x00\x00\x00\x00\x00\x0a\x95\x2a\xff\xfe\xad\xd6\x4f\x02\x01\x08\x95\x2a\xad\xd6\x4f",
signature = "IPv6 from Sparta" ]
考虑到在"以太网 pigsty"中包含目标源 MAC 地址是可选的,即使不使用任何"毛绒字段",我们也能完成任务。
当你需要在环境中测试新协议或其他有趣的异常情况时,这非常有用。通过这种原始方式,pig 可以继续为你提供帮助。
将以下数据保存为 "oink.pigsty":
[ signature = "oink",
ip.version = 4,
ip.ihl = 5,
ip.tos = 0,
ip.src = 127.0.0.1,
ip.dst = user-defined-ip,
ip.protocol = 17,
udp.dst = 1008,
udp.src = 32000,
udp.payload = "Oink!!\n" ]
在另一个 tty 上,以 UDP 模式 运行 netcat 监听端口 1008:
[email protected]:~# nc -u -l -p 1008
现在运行 pig,使用 "oink.pigsty",并将目标指定为 loopback:
[email protected]:~# pig --signatures=oink.pigsty --targets=127.0.0.1\
> --gateway=10.0.2.2 --net-mask=255.255.255.0 --lo-iface=eth0
netcat 应该开始收到多个 oinks,是的,恭喜!!pig 已经在你的系统上运行了!;)
尝试嗅探你的网络以获取更多关于这些在你的接口中流动的 UDP 数据包 的信息……
玩得开心!
| 字段 | 含义 | 协议 | 数据类型 | 示例定义 |
|---|
signature | 签名名称 | - | 字符串 | signature = "Udp flood" |
eth.hwdst | 以太网目标 MAC | Ethernet | MAC 地址 | eth.hwdst = "00:de:ad:be:ef:00" |
eth.hwsrc | 以太网源 MAC | Ethernet | MAC 地址 | eth.hwsrc = "00:de:ad:be:ef:00" |
eth.type | 以太类型 | Ethernet | 数字 | eth.type = 0x0800 |
eth.payload | 以太网负载 | Ethernet | 字符串 | eth.payload = "f\x00ob\x04r" |
ip.version | IP 版本 | IP | 数字 | ip.version = 4 |
ip.ihl | 互联网头部长度 | IP | 数字 | ip.ihl = 5 |
ip.tos | 服务类型 | IP | 数字 | ip.tos = 0 |
ip.tlen | 总长度 | IP | 数字 | ip.tlen = 20 |
ip.id | 数据包 ID | IP | 数字 | ip.id = 0xbeef |
ip.flags | IP 标志 | IP | 数字 | ip.flags = 4 |
ip.offset | 分片偏移 | IP | 数字 | ip.offset = 0 |
ip.ttl | 生存时间 | IP | 数字 | ip.ttl = 64 |
ip.protocol | 协议 | IP | 数字 | ip.protocol = 6 |
ip.checksum | 校验和 | IP | 数字 | ip.checksum = 0 |
ip.src | 源地址 | IP | IP 地址 | ip.src = 192.30.70.3 |
ip.dst | 目标地址 | IP | IP 地址 | ip.dst = 192.30.70.3 |
ip.payload | IP 原始负载 | IP | 字符串 | ip.payload = "\x01\x02" |
tcp.src | 源端口 | TCP | 数字 | tcp.src = 80 |
tcp.dst | 目标端口 | TCP | 数字 | tcp.dst = 21 |
tcp.seqno | 序列号 | TCP | 数字 | tcp.seqno = 10202 |
tcp.ackno | 确认号 | TCP | 数字 | tcp.ackno = 10200 |
tcp.size | TCP 长度 | TCP | 数字 | tcp.size = 4 |
tcp.reserv | TCP 保留字段 | TCP | 数字 | tcp.reserv = 0 |
tcp.urg | TCP 紧急标志 | TCP | 位 | tcp.urg = 0 |
tcp.ack | TCP 确认标志 | TCP | 位 | tcp.ack = 1 |
tcp.psh | TCP 推送标志 | TCP | 位 | tcp.psh = 0 |
tcp.rst | TCP 复位标志 | TCP | 位 | tcp.rst = 0 |
tcp.syn | TCP 同步标志 | TCP | 位 | tcp.syn = 0 |
tcp.fin | TCP 结束标志 | TCP | 位 | tcp.fin = 0 |
tcp.wsize | TCP 窗口大小 | TCP | 数字 | tcp.wsize = 0 |
tcp.checksum | 校验和 | TCP | 数字 | tcp.checksum = 0 |
tcp.urgp | 紧急指针 | TCP | 数字 | tcp.urgp = 0 |
tcp.payload | 负载 | TCP | 字符串 | tcp.payload = "\x01abc" |
udp.src | 源端口 | UDP | 数字 | udp.src = 53 |
udp.dst | 目标端口 | UDP | 数字 | udp.dst = 7 |
udp.size | UDP 长度 | UDP | 数字 | udp.size = 8 |
udp.checksum | 校验和 | UDP | 数字 | udp.checksum = 0 |
udp.payload | 负载 | UDP | 数字 | udp.payload = "boo!" |
icmp.type | ICMP 类型 | ICMP | 数字 | icmp.type = 0 |
icmp.code | ICMP 代码 | ICMP | 数字 | icmp.code = 0 |
icmp.checksum | 校验和 | ICMP | 数字 | icmp.checksum = 0 |
icmp.payload | 负载 | ICMP | 字符串 | icmp.payload = "ping!" |
arp.hwtype | ARP 硬件类型 | ARP | 数字 | arp.hwtype = 0x1 |
arp.ptype | ARP 协议类型 | ARP | 数字 | arp.ptype = 0x0800 |
arp.hwlen | ARP 硬件长度 | ARP | 数字 | arp.hwlen = 6 |
arp.opcode | ARP 操作码 | ARP | 数字 | arp.opcode = 2 |
arp.hwsrc | ARP 源硬件地址 | ARP | MAC 地址 | arp.hwsrc = "de:ad:be:ef:0:0" |
arp.psrc | ARP 源协议地址 | ARP | IP 地址 | arp.psrc = 192.30.70.3 |
arp.hwdst | ARP 目标硬件地址 | ARP | MAC 地址 | arp.hwdst = "de:ad:be:ef:0:0" |
arp.pdst | ARP 目标协议地址 | ARP | IP 地址 | arp.pdst = 192.30.70.3 |
north-american-ip | 北美的 IP 地址 |
south-american-ip | 南美的 IP 地址 |
asian-ip | 亚洲的 IP 地址 |
european-ip | 欧洲的 IP 地址 |
| 子任务 |
|---|
| 功能 |
|---|
| 手册 |
|---|
pcap-import | 从 PCAP 文件导入数据包到 pigsty 文件 | cat doc/pcap-import.md |
shell | 以交互模式执行 pig | cat doc/shell.md |