From 3c23c38d2583fda7984ecce08f840a20a013162d Mon Sep 17 00:00:00 2001 From: alterdekim Date: Mon, 9 Dec 2024 19:02:35 +0300 Subject: [PATCH] modified: Cargo.lock modified: frida_cli/Cargo.toml modified: frida_cli/src/main.rs modified: frida_client/Cargo.toml modified: frida_client/src/client.rs new file: frida_client/src/lib.rs renamed: frida_cli/src/config/mod.rs -> frida_core/src/config.rs modified: frida_core/src/device.rs modified: frida_core/src/lib.rs modified: frida_core/src/linux_tun.rs renamed: frida_cli/src/obfs.rs -> frida_core/src/obfs.rs renamed: frida_cli/src/udp.rs -> frida_core/src/udp.rs modified: frida_core/src/win_tun.rs --- Cargo.lock | 12 ++++ frida_cli/Cargo.toml | 10 +++ frida_cli/src/main.rs | 22 +++---- frida_client/Cargo.toml | 5 +- frida_client/src/client.rs | 62 +++++++++---------- frida_client/src/lib.rs | 1 + .../config/mod.rs => frida_core/src/config.rs | 0 frida_core/src/device.rs | 10 +-- frida_core/src/lib.rs | 3 + frida_core/src/linux_tun.rs | 8 ++- {frida_cli => frida_core}/src/obfs.rs | 0 {frida_cli => frida_core}/src/udp.rs | 0 frida_core/src/win_tun.rs | 48 +++++++++++++- 13 files changed, 122 insertions(+), 59 deletions(-) create mode 100644 frida_client/src/lib.rs rename frida_cli/src/config/mod.rs => frida_core/src/config.rs (100%) rename {frida_cli => frida_core}/src/obfs.rs (100%) rename {frida_cli => frida_core}/src/udp.rs (100%) diff --git a/Cargo.lock b/Cargo.lock index 77c7e8c..00950fc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1646,6 +1646,18 @@ checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b" [[package]] name = "frida_cli" version = "0.2.0" +dependencies = [ + "clap", + "env_logger", + "frida_client", + "frida_core", + "log", + "serde", + "serde_derive", + "serde_yaml", + "tokio 1.42.0", + "tokio-util", +] [[package]] name = "frida_client" diff --git a/frida_cli/Cargo.toml b/frida_cli/Cargo.toml index 874cdeb..3a84d31 100644 --- a/frida_cli/Cargo.toml +++ b/frida_cli/Cargo.toml @@ -10,3 +10,13 @@ readme = "../README.md" workspace = "../" [dependencies] +clap = "2.33" +env_logger = "0.9" +log = "0.4.20" +serde = "1.0" +serde_derive = "1.0.190" +serde_yaml = "0.9.34" +tokio = { version = "1", features = ["full", "signal", "tracing"] } +tokio-util = "0.7.12" +frida_core = { path = "../frida_core" } +frida_client = { path = "../frida_client" } \ No newline at end of file diff --git a/frida_cli/src/main.rs b/frida_cli/src/main.rs index 9398267..b3dd3a0 100644 --- a/frida_cli/src/main.rs +++ b/frida_cli/src/main.rs @@ -1,16 +1,12 @@ use std::{fs, net::{Ipv4Addr}, str}; -use clap::{App, Arg, ArgMatches}; +use clap::{crate_authors, crate_name, crate_version, App, Arg, ArgMatches}; use env_logger::Builder; use log::{error, LevelFilter}; -use crate::config::{ ServerConfiguration, ClientConfiguration, ObfsProtocol, ServerPeer }; -use crate::client::{desktop::DesktopClient, general::VpnClient}; +use frida_core::config::{ ServerConfiguration, ClientConfiguration, ObfsProtocol, ServerPeer }; +use frida_client::client::{desktop::DesktopClient, general::VpnClient}; -mod obfs; -mod server; -mod client; -mod udp; -mod config; +//mod server; fn generate_server_config(matches: &ArgMatches, config_path: &str) { let bind_address = matches.value_of("bind-address").expect("No bind address specified"); @@ -62,7 +58,7 @@ fn generate_peer_config(matches: &ArgMatches, config_path: &str, cfg_raw: &Strin async fn init_server(cfg_raw: &str, s_interface: Option<&str>) { let config: ServerConfiguration = serde_yaml::from_str(cfg_raw).expect("Bad server config file structure"); - server::server_mode(config, s_interface).await; + //server::server_mode(config, s_interface).await; } async fn init_client(cfg_raw: &str, s_interface: Option) { @@ -74,16 +70,14 @@ async fn init_client(cfg_raw: &str, s_interface: Option) { #[tokio::main] async fn main() { - //console_subscriber::init(); - // Initialize the logger with 'info' as the default level Builder::new() .filter(None, LevelFilter::Info) .init(); - let matches = App::new("Frida") - .version("0.1.2") - .author("alterwain") + let matches = App::new(crate_name!()) + .version(crate_version!()) + .author(crate_authors!()) .about("VPN software") .arg(Arg::with_name("mode") .required(true) diff --git a/frida_client/Cargo.toml b/frida_client/Cargo.toml index b29ae49..20f1edd 100644 --- a/frida_client/Cargo.toml +++ b/frida_client/Cargo.toml @@ -8,9 +8,8 @@ keywords = ["tun", "network", "tunnel", "vpn"] categories = ["network-programming", "asynchronous"] readme = "../README.md" -[[bin]] -name = "frida_client" -path = "src/client.rs" +[lib] +crate-type = ["staticlib", "cdylib", "lib"] [dependencies] frida_core = { path = "../frida_core", package = "frida_core" } diff --git a/frida_client/src/client.rs b/frida_client/src/client.rs index c09d83b..90b49dd 100644 --- a/frida_client/src/client.rs +++ b/frida_client/src/client.rs @@ -1,7 +1,5 @@ pub mod general { - use crate::config::ClientConfiguration; - use async_channel::{Receiver, Sender}; - use futures::{stream::{SplitSink, SplitStream}, SinkExt, StreamExt}; + use frida_core::config::ClientConfiguration; use tokio_util::{codec::Framed, sync::CancellationToken}; use tokio::{net::UdpSocket, sync::{Mutex, mpsc}, io::{AsyncWriteExt, AsyncReadExt}, fs::File}; use log::{error, info, warn}; @@ -13,9 +11,7 @@ pub mod general { use std::net::Ipv4Addr; use x25519_dalek::{PublicKey, StaticSecret}; - use crate::udp::{UDPVpnPacket, UDPVpnHandshake, UDPSerializable}; - - use frida_core::tun::create_tun; + use frida_core::udp::{UDPVpnPacket, UDPVpnHandshake, UDPSerializable}; use frida_core::{DeviceReader, DeviceWriter}; pub trait VpnClient { @@ -24,13 +20,11 @@ pub mod general { pub struct CoreVpnClient { pub client_config: ClientConfiguration, - pub dev_reader: DeviceReader, - pub dev_writer: DeviceWriter, pub close_token: CancellationToken } impl CoreVpnClient { - pub async fn start(&mut self, sock: UdpSocket) { + pub async fn start(&mut self, sock: UdpSocket, dev_reader: DeviceReader, dev_writer: DeviceWriter) { info!("Starting client..."); let dr_cancel: CancellationToken = CancellationToken::new(); @@ -59,11 +53,23 @@ pub mod general { let s_cipher = cipher_shared.clone(); - let _ = self.dev_writer.write(handshake.serialize()).await; + let _ = dev_writer.write(&handshake.serialize()).await; - let mut buf = vec![0; 1400]; // mtu let mut buf1 = vec![0; 4096]; // should be changed to less bytes + tokio::spawn(async move { + let mut buf = vec![0; 1400]; // mtu + loop { + match dev_reader.read(&mut buf).await { + Ok(n) => { + info!("Read from tun."); // hex::encode(&buf[..n]) + dx.send(buf[..n].to_vec()).unwrap(); + }, + Err(e) => { error!("{}", e); } + } + } + }); + loop { tokio::select! { _ = self.close_token.cancelled() => { @@ -76,7 +82,7 @@ pub mod general { if let Some(bytes) = rr { info!("Write to tun. len={:?}", bytes.len()); - if let Err(e) = self.dev_writer.write(&bytes).await { + if let Err(e) = dev_writer.write(&bytes).await { error!("Writing error: {:?}", e); } /* if let Err(e) = self.dev_writer.flush().await { @@ -86,6 +92,7 @@ pub mod general { } rr2 = mx.recv() => { if let Some(bytes) = rr2 { + info!("Got info for sending"); let s_c = s_cipher.lock().await; if s_c.is_some() { @@ -106,12 +113,6 @@ pub mod general { } } } - rr = self.dev_reader.read(&mut buf) => { - if let Ok(n) = rr { - info!("Read from tun."); // hex::encode(&buf[..n]) - dx.send(buf[..n].to_vec()).unwrap(); - } - } rr = sock_rec.recv(&mut buf1) => { if let Ok(l) = rr { info!("Read from socket"); @@ -190,11 +191,12 @@ pub mod android { } pub mod desktop { - use crate::client::general::{CoreVpnClient, DevReader, DevWriter, VpnClient}; - use crate::config::ClientConfiguration; - use frida_core::create; + use std::net::Ipv4Addr; + + use crate::client::general::{CoreVpnClient, VpnClient}; + use frida_core::config::ClientConfiguration; + use frida_core::tun::create_tun; use frida_core::device::AbstractDevice; - use futures::{SinkExt, StreamExt}; use log::info; use tokio::net::UdpSocket; use tokio::sync::Mutex; @@ -270,21 +272,19 @@ pub mod desktop { info!("s_interface: {:?}", &self.s_interface); info!("client_address: {:?}", &self.client_config.client.address); let mut config = AbstractDevice::default(); - config.address(&self.client_config.client.address) - .netmask("255.255.255.255") - .destination("10.66.66.1") + config.address(self.client_config.client.address.parse().unwrap()) + .netmask(std::net::IpAddr::V4(Ipv4Addr::new(255, 255, 255, 255))) + .destination(std::net::IpAddr::V4(Ipv4Addr::new(10, 66, 66, 1))) .mtu(1400) - .tun_name("tun0") - .up(); + .tun_name("tun0"); info!("SSS: {:?}", &self.client_config.server.endpoint); let sock = UdpSocket::bind(("0.0.0.0", 0)).await.unwrap(); sock.connect(&self.client_config.server.endpoint).await.unwrap(); - let dev = create(&config).unwrap(); - let (mut dev_writer , mut dev_reader) = dev.into_framed().split(); + let (dev_reader, dev_writer) = create_tun(config); - let mut client = CoreVpnClient{ client_config: self.client_config.clone(), dev_reader: DevReader{ dr: dev_reader }, dev_writer: DevWriter{dr: dev_writer }, close_token: tokio_util::sync::CancellationToken::new()}; + let mut client = CoreVpnClient{ client_config: self.client_config.clone(), close_token: tokio_util::sync::CancellationToken::new()}; info!("Platform specific code"); /* #[cfg(target_os = "linux")] @@ -293,7 +293,7 @@ pub mod desktop { configure_routes(&s_a.ip().to_string(), self.s_interface.clone()); }*/ - client.start(sock).await; + client.start(sock, dev_reader, dev_writer).await; } } } \ No newline at end of file diff --git a/frida_client/src/lib.rs b/frida_client/src/lib.rs new file mode 100644 index 0000000..3935517 --- /dev/null +++ b/frida_client/src/lib.rs @@ -0,0 +1 @@ +pub mod client; \ No newline at end of file diff --git a/frida_cli/src/config/mod.rs b/frida_core/src/config.rs similarity index 100% rename from frida_cli/src/config/mod.rs rename to frida_core/src/config.rs diff --git a/frida_core/src/device.rs b/frida_core/src/device.rs index fce9b20..78870ff 100644 --- a/frida_core/src/device.rs +++ b/frida_core/src/device.rs @@ -3,11 +3,11 @@ use std::net::IpAddr; #[derive(Default)] pub struct AbstractDevice { - address: Option, - netmask: Option, - destination: Option, - mtu: Option, - tun_name: Option + pub(crate) address: Option, + pub(crate) netmask: Option, + pub(crate) destination: Option, + pub(crate) mtu: Option, + pub(crate) tun_name: Option } impl AbstractDevice { diff --git a/frida_core/src/lib.rs b/frida_core/src/lib.rs index 5049970..0e4f0e5 100644 --- a/frida_core/src/lib.rs +++ b/frida_core/src/lib.rs @@ -1,5 +1,8 @@ pub mod device; pub mod tun; +pub mod obfs; +pub mod udp; +pub mod config; #[cfg(target_os = "windows")] mod win_tun; diff --git a/frida_core/src/linux_tun.rs b/frida_core/src/linux_tun.rs index ed02c08..fbc5e85 100644 --- a/frida_core/src/linux_tun.rs +++ b/frida_core/src/linux_tun.rs @@ -7,9 +7,11 @@ use std::os::unix::io::AsRawFd; pub fn create(cfg: AbstractDevice) -> (DeviceReader, DeviceWriter) { let tun = Arc::new( Tun::builder() - .name("") // if name is empty, then it is set by kernel. - .tap() // uses TAP instead of TUN (default). - .packet_info() // avoids setting IFF_NO_PI. + .name(cfg.tun_name.unwrap()) // if name is empty, then it is set by kernel. + .mtu(cfg.mtu.unwrap()) + .address(cfg.address.unwrap()) + .netmask(cfg.netmask.unwrap()) + .destination(cfg.destination.unwrap()) .up() // or set it up manually using `sudo ip link set up`. .try_build() // or `.try_build_mq(queues)` for multi-queue support. .unwrap(), diff --git a/frida_cli/src/obfs.rs b/frida_core/src/obfs.rs similarity index 100% rename from frida_cli/src/obfs.rs rename to frida_core/src/obfs.rs diff --git a/frida_cli/src/udp.rs b/frida_core/src/udp.rs similarity index 100% rename from frida_cli/src/udp.rs rename to frida_core/src/udp.rs diff --git a/frida_core/src/win_tun.rs b/frida_core/src/win_tun.rs index 371f8a6..1c18a7d 100644 --- a/frida_core/src/win_tun.rs +++ b/frida_core/src/win_tun.rs @@ -10,15 +10,57 @@ pub fn create(cfg: AbstractDevice) -> (DeviceReader, DeviceWriter) { let wintun = unsafe { wintun::load_from_path("wintun.dll") } .expect("Failed to load wintun dll"); - //Try to open an adapter with the name "Demo" - let adapter = match wintun::Adapter::open(&wintun, "Demo") { + let tun_name = match cfg.tun_name { + Some(n) => n, + None => "Demo".into() + }; + + //Try to open an adapter with the certain name + let adapter = match wintun::Adapter::open(&wintun, &tun_name) { Ok(a) => a, Err(_) => { - wintun::Adapter::create(&wintun, "Demo", "Example", None) + wintun::Adapter::create(&wintun, &tun_name, "FridaVPN", None) .expect("Failed to create wintun adapter!") } }; + let args = &["interface", "ipv4", "set", "interface", &tun_name, "metric=5"]; + let _ = wintun::run_command("netsh", args).unwrap(); + + let mut gateway = "gateway=".to_owned(); + gateway.push_str(&cfg.destination.unwrap().to_string()); + + let mut address = cfg.address.unwrap().to_string().to_owned(); + address.push_str("/32"); + + let args = &[ + "interface", + "ipv4", + "set", + "address", + &tun_name, + "static", + &address, + &gateway, + ]; + + let _ = wintun::run_command("netsh", args).unwrap(); + + let mut mtu = "mtu=".to_owned(); + mtu.push_str(&cfg.mtu.unwrap().to_string()); + + let args = &[ + "interface", + "ipv4", + "set", + "subinterface", + &tun_name, + &mtu, + "store=persistent" + ]; + + let _ = wintun::run_command("netsh", args).unwrap(); + let session = Arc::new(adapter.start_session(wintun::MAX_RING_CAPACITY).unwrap()); let reader_session = session.clone(); let writer_session = session.clone();