use crate::model::{EthTable, StatusTable};
use crate::state::BruteForceState;
use pnet::datalink::Channel::Ethernet;
use pnet::datalink::{self, DataLinkSender};
use pnet::packet::ethernet::{EtherTypes, MutableEthernetPacket};
use pnet::packet::ipv4::{Ipv4Flags, MutableIpv4Packet};
use pnet::packet::udp::{ipv4_checksum, MutableUdpPacket};
use pnet::packet::{ip::IpNextHeaderProtocols, Packet};
use rand::Rng;
use std::error::Error;
use std::fmt;
use std::net::Ipv4Addr;
use std::sync::{Arc, Mutex};
use std::time::Duration;
use std::{i32, thread};
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum SendDogError {
InterfaceNotFound { device: String },
UnsupportedChannelType { interface: String },
ChannelCreationFailed { interface: String, source: String },
MissingDestinationMac,
InvalidDnsServer { dns_server: String, source: String },
SendFailed { source: String },
MissingDestinationInterface,
}
impl fmt::Display for SendDogError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
SendDogError::InterfaceNotFound { device } => {
write!(f, "未找到可用于原始发包的网络接口: {}", device)
}
SendDogError::UnsupportedChannelType { interface } => {
write!(f, "网络接口 {} 返回了不支持的数据链路通道类型", interface)
}
SendDogError::ChannelCreationFailed { interface, source } => write!(
f,
"创建网络接口 {} 的数据链路通道失败: {}",
interface, source
),
SendDogError::MissingDestinationMac => write!(
f,
"目标MAC地址为空,禁止降级为UDP socket发送,请先完成下一跳MAC解析"
),
SendDogError::InvalidDnsServer { dns_server, source } => {
write!(
f,
"DNS服务器地址 {} 无法解析为IPv4地址: {}",
dns_server, source
)
}
SendDogError::SendFailed { source } => write!(f, "发送原始DNS数据包失败: {}", source),
SendDogError::MissingDestinationInterface => {
write!(f, "未指定用于发送数据包的目标网络接口")
}
}
}
}
impl Error for SendDogError {}
#[derive(Clone)]
pub struct SendDog {
ether: EthTable,
dns: Vec<String>,
handle: Arc<Mutex<Box<dyn DataLinkSender>>>,
index: u16,
lock: Arc<Mutex<()>>,
increate_index: bool,
flag_id: u16,
flag_id2: u16,
}
impl SendDog {
pub fn new(ether: EthTable, dns: Vec<String>, flag_id: u16) -> Result<SendDog, SendDogError> {
let interfaces = datalink::interfaces();
let interface = interfaces
.iter()
.find(|iface| iface.name == ether.device && !iface.is_loopback())
.ok_or_else(|| SendDogError::InterfaceNotFound {
device: ether.device.clone(),
})?;
let (mut _handle, _) = match datalink::channel(&interface, Default::default()) {
Ok(Ethernet(_tx, _rx)) => (_tx, _rx),
Ok(_) => {
return Err(SendDogError::UnsupportedChannelType {
interface: interface.name.clone(),
});
}
Err(e) => {
return Err(SendDogError::ChannelCreationFailed {
interface: interface.name.clone(),
source: e.to_string(),
});
}
};
let handle: Arc<Mutex<Box<dyn DataLinkSender>>> = Arc::new(Mutex::new(_handle));
let default_dns: Vec<String>;
if dns.len() == 0 {
default_dns = vec![
"223.5.5.5".to_string(),
"223.6.6.6".to_string(),
"180.76.76.76".to_string(),
"119.29.29.29".to_string(),
"182.254.116.116".to_string(),
"114.114.114.115".to_string(),
];
} else {
default_dns = dns;
}
Ok(SendDog {
ether,
dns: default_dns,
flag_id,
handle,
index: 10000,
lock: Mutex::new(()).into(),
increate_index: true,
flag_id2: 0,
})
}
pub fn chose_dns(&self) -> String {
let mut rng = rand::thread_rng();
let index = rng.gen_range(0..self.dns.len());
self.dns[index].to_owned()
}
pub fn send(
&self,
domain: String,
dnsname: String,
src_port: u16,
flag_id: u16,
) -> Result<(), SendDogError> {
if self.ether.dst_mac == pnet::util::MacAddr::zero() {
return Err(SendDogError::MissingDestinationMac);
}
let dns_query: Vec<u8> = build_dns_query(domain.as_str(), self.flag_id * 100 + flag_id);
let ipv4_source: Ipv4Addr = self.ether.src_ip;
let ipv4_destination: Ipv4Addr =
dnsname.parse().map_err(|error: std::net::AddrParseError| {
SendDogError::InvalidDnsServer {
dns_server: dnsname.clone(),
source: error.to_string(),
}
})?;
let dns_query_len = dns_query.len();
let ipv4_header_len = 20;
let udp_header_len = 8;
let total_length: u16 = (ipv4_header_len + udp_header_len + dns_query_len) as _;
let mut udp_buffer: Vec<u8> = Vec::with_capacity(udp_header_len + dns_query_len);
udp_buffer.resize(8 + dns_query_len, 0u8);
let mut udp_header = MutableUdpPacket::new(&mut udp_buffer).unwrap();
udp_header.set_source(src_port);
udp_header.set_destination(53);
udp_header.set_length(udp_header_len as u16 + dns_query_len as u16);
udp_header.set_payload(&dns_query);
let mut ipv4_buffer = [0u8; 20];
let mut ipv4_header = MutableIpv4Packet::new(&mut ipv4_buffer).unwrap();
ipv4_header.set_header_length(69);
ipv4_header.set_total_length(total_length);
ipv4_header.set_next_level_protocol(IpNextHeaderProtocols::Udp);
ipv4_header.set_source(ipv4_source);
ipv4_header.set_destination(ipv4_destination);
ipv4_header.set_identification(5636);
ipv4_header.set_ttl(64);
ipv4_header.set_version(4);
ipv4_header.set_flags(Ipv4Flags::DontFragment);
let mut ethernet_buffer = [0u8; 14];
let mut ethernet_packet = MutableEthernetPacket::new(&mut ethernet_buffer).unwrap();
ethernet_packet.set_destination(self.ether.dst_mac);
ethernet_packet.set_source(self.ether.src_mac);
ethernet_packet.set_ethertype(EtherTypes::Ipv4);
let checksum = pnet::packet::ipv4::checksum(&ipv4_header.to_immutable());
ipv4_header.set_checksum(checksum);
let checksum = ipv4_checksum(&udp_header.to_immutable(), &ipv4_source, &ipv4_destination);
udp_header.set_checksum(checksum);
let mut final_packet = Vec::new();
final_packet.extend_from_slice(ethernet_packet.packet());
final_packet.extend_from_slice(ipv4_header.packet());
final_packet.extend_from_slice(udp_header.packet());
let mut handle = self.handle.lock().unwrap();
let res = {
handle.send_to(&final_packet, None)
};
match res {
Some(Ok(())) => Ok(()),
Some(Err(e)) => Err(SendDogError::SendFailed {
source: e.to_string(),
}),
None => Err(SendDogError::MissingDestinationInterface),
}
}
pub fn build_status_table(
&mut self,
state: &BruteForceState,
domain: &str,
dns: &str,
domain_level: isize,
) -> (u16, u16) {
let _lock = self.lock.lock().unwrap(); if self.index >= 60000 {
self.flag_id2 += 1;
self.index = 10000;
}
if self.flag_id2 > 99 {
self.increate_index = false;
}
if self.increate_index {
self.index += 1;
} else {
loop {
match state.pop_from_stack() {
Some(v) => {
let (flag_id2, index) = generate_flag_index_from_map(v);
self.flag_id2 = flag_id2;
self.index = index;
break;
}
None => {
thread::sleep(Duration::from_millis(520));
}
}
}
}
let index = generate_map_index(self.flag_id2, self.index);
let status = StatusTable {
domain: domain.to_string(),
dns: dns.to_string(),
time: chrono::Utc::now().timestamp() as u64, retry: 0,
domain_level,
};
state.append_status(status, index as u32);
(self.flag_id2, self.index)
}
}
pub fn generate_map_index(flag_id2: u16, index: u16) -> i32 {
(flag_id2 as i32 * 60000) + (index as i32)
}
pub fn generate_flag_index_from_map(index: usize) -> (u16, u16) {
let yuzhi: usize = 60000;
let flag2 = index / yuzhi;
let index2 = index % yuzhi;
(flag2 as u16, index2 as u16)
}
fn build_dns_query(domain: &str, flag_id: u16) -> Vec<u8> {
let mut buffer = Vec::new();
buffer.push((flag_id >> 8) as u8); buffer.push(flag_id as u8); buffer.extend_from_slice(&[0x01, 0x00]); buffer.extend_from_slice(&[0x00, 0x01]); buffer.extend_from_slice(&[0x00, 0x00]); buffer.extend_from_slice(&[0x00, 0x00]); buffer.extend_from_slice(&[0x00, 0x00]);
for label in domain.split('.') {
buffer.push(label.len() as u8);
buffer.extend_from_slice(label.as_bytes());
}
buffer.extend_from_slice(&[0x00]);
buffer.extend_from_slice(&[0x00, 0x01]); buffer.extend_from_slice(&[0x00, 0x01]);
buffer
}
#[cfg(test)]
mod tests {
use super::*;
use pnet::util::MacAddr;
#[test]
fn new_returns_error_for_missing_interface_instead_of_panicking() {
let ether = EthTable {
src_ip: Ipv4Addr::new(127, 0, 0, 1),
device: "__rsubdomain_missing_interface__".to_string(),
src_mac: MacAddr::new(0, 0, 0, 0, 0, 1),
dst_mac: MacAddr::new(0, 0, 0, 0, 0, 2),
};
let result = SendDog::new(ether, Vec::new(), 1);
assert!(matches!(
result,
Err(SendDogError::InterfaceNotFound { device })
if device == "__rsubdomain_missing_interface__"
));
}
}