fix: fixed weird issues with querying routes
this just involved a better understanding of the data types provided by libnl and some refactoring to make querying as a user of the libnl library easier
This commit is contained in:
@@ -1,8 +1,15 @@
|
||||
[package]
|
||||
name = "beacon"
|
||||
name = "ex-revshell-beacon"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
tokio = { version = "1.21.2", features = ["net", "rt", "macros", "rt-multi-thread", "io-util", "time"] }
|
||||
nl-sys = { path = "../../../nl-sys" }
|
||||
pcap-sys = { path = "../../../pcap-sys" }
|
||||
anyhow = "1.0.70"
|
||||
tokio-stream = "0.1.14"
|
||||
log = "0.4.17"
|
||||
simple_logger = "4.1.0"
|
||||
@@ -1,3 +1,118 @@
|
||||
fn main() {
|
||||
println!("Hello, world!");
|
||||
use std::{net::Ipv4Addr, collections::HashMap};
|
||||
|
||||
use anyhow::{anyhow, bail};
|
||||
use tokio::time::{Duration, interval};
|
||||
use tokio_stream::StreamExt;
|
||||
|
||||
use nl_sys::{netlink, route};
|
||||
use pcap_sys::packets::*;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> anyhow::Result<()> {
|
||||
// commented out because it's hard to easily input an IP by command line with docker compose
|
||||
// let mut args = std::env::args();
|
||||
// args.next();
|
||||
// let target = args.next()
|
||||
// .map(|s| s.parse::<Ipv4Addr>().ok())
|
||||
// .flatten()
|
||||
// .ok_or(anyhow!("Please specify a target IP"))?;
|
||||
|
||||
// print!("Please enter the target IP (found with `docker-compose exec examples_revshell_server ip a`, e.x. 172.19.0.2): ");
|
||||
// std::io::stdout().flush()?;
|
||||
// let stdin = std::io::stdin();
|
||||
// let mut target = String::new();
|
||||
// stdin.read_line(&mut target)?;
|
||||
// let target = target.trim().parse::<Ipv4Addr>()?;
|
||||
let target: Ipv4Addr = "172.19.0.2".parse().unwrap();
|
||||
|
||||
let (src_mac, dst_mac, srcip) = {
|
||||
let socket = netlink::Socket::new()?;
|
||||
|
||||
let routes = socket.get_routes()?;
|
||||
let neighs = socket.get_neigh()?;
|
||||
let links = socket.get_links()?;
|
||||
|
||||
let srcip = route::get_srcip_for_dstip(&routes, target)
|
||||
.ok_or(anyhow!("Unable to find a route to the IP"))?;
|
||||
|
||||
let (target_link, dst_mac) = route::get_neigh_for_addr(&routes, &neighs, &links, &srcip.into())
|
||||
.ok_or(anyhow!("Unable to find local interface to use"))?;
|
||||
|
||||
let src_mac = target_link.addr().hw_address();
|
||||
|
||||
(
|
||||
TryInto::<[u8;6]>::try_into(src_mac).unwrap(),
|
||||
TryInto::<[u8;6]>::try_into(dst_mac).unwrap(),
|
||||
srcip
|
||||
)
|
||||
};
|
||||
|
||||
let mut interfaces = pcap_sys::PcapDevIterator::new()?;
|
||||
|
||||
let interface_name = interfaces
|
||||
.find(|eth| eth.starts_with("eth"))
|
||||
.ok_or(anyhow!("could not get an ethernet interface"))?;
|
||||
|
||||
let mut interface = pcap_sys::Interface::<pcap_sys::DevDisabled>::new(&interface_name)?;
|
||||
|
||||
interface.set_buffer_size(8192)?;
|
||||
interface.set_non_blocking(true)?;
|
||||
interface.set_promisc(false)?;
|
||||
interface.set_timeout(10)?;
|
||||
|
||||
let mut interface = interface.activate()?;
|
||||
|
||||
interface.set_filter("inbound and udp port 54248", true, None)?;
|
||||
|
||||
if interface.datalink() != pcap_sys::consts::DLT_EN10MB {
|
||||
bail!("interface does not support ethernet")
|
||||
}
|
||||
|
||||
enum EventType {
|
||||
Packet(Result<EthernetPacket, pcap_sys::error::Error>),
|
||||
Update
|
||||
}
|
||||
|
||||
let mut packets = interface.stream()?;
|
||||
let mut update_interval = interval(Duration::from_millis(500));
|
||||
let mut current_packet_id = 0;
|
||||
let mut sent_updates: HashMap<i32, bool> = HashMap::new();
|
||||
|
||||
while let Some(evt) = tokio::select! {
|
||||
v = packets.next() => v.map(EventType::Packet),
|
||||
_ = update_interval.tick() => Some(EventType::Update)
|
||||
} {
|
||||
match evt {
|
||||
EventType::Packet(Ok(pkt)) => {
|
||||
let eth_pkt = pkt.pkt();
|
||||
let Ok(Layer3Pkt::IPv4Pkt(ip_pkt)) = eth_pkt.get_layer3_pkt() else { continue; };
|
||||
let Ok(Layer4Pkt::UDP(udp_pkt)) = ip_pkt.get_layer4_packet() else { continue; };
|
||||
|
||||
let data = udp_pkt.get_data();
|
||||
|
||||
let Ok(resp_id) = TryInto::<[u8;4]>::try_into(&data[..4]) else { continue; };
|
||||
let resp_id = i32::from_be_bytes(resp_id);
|
||||
|
||||
if sent_updates.contains_key(&resp_id) {
|
||||
sent_updates.remove(&resp_id);
|
||||
println!("Packet {resp_id} has received a response");
|
||||
}
|
||||
}
|
||||
EventType::Update => {
|
||||
let unacknowledged_packets = sent_updates.keys().collect::<Vec<_>>();
|
||||
println!("Currently unacknowledged packets: {unacknowledged_packets:?}");
|
||||
current_packet_id += 1;
|
||||
sent_updates.insert(current_packet_id, false);
|
||||
|
||||
let udp_packet = UDPPacket::construct(54248, 54248, current_packet_id.to_be_bytes().to_vec());
|
||||
let ip_packet = IPv4Packet::construct(srcip, target, &Layer4Packet::UDP(udp_packet));
|
||||
let eth_packet = EthernetPacket::construct(src_mac, dst_mac, &Layer3Packet::IPv4(ip_packet));
|
||||
|
||||
packets.sendpacket(eth_packet.pkt())?;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
[package]
|
||||
name = "server"
|
||||
name = "ex-revshell-server"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1.0.70"
|
||||
@@ -1,3 +1,19 @@
|
||||
fn main() {
|
||||
println!("Hello, world!");
|
||||
use std::net::UdpSocket;
|
||||
|
||||
fn main() -> anyhow::Result<()> {
|
||||
let input = UdpSocket::bind("0.0.0.0:54248")?;
|
||||
|
||||
loop {
|
||||
let mut buf = [0u8; 4];
|
||||
|
||||
let Ok((amount, src)) = input.recv_from(&mut buf[..]) else { continue; };
|
||||
|
||||
if amount != 4 {
|
||||
continue;
|
||||
}
|
||||
|
||||
println!("Received packet: {}", i32::from_be_bytes(buf));
|
||||
|
||||
let Ok(_) = input.send_to(&buf, src) else { continue; };
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user