MacOS stuff
This commit is contained in:
parent
39d9e14ddb
commit
8c51b1c20f
9
Cargo.lock
generated
9
Cargo.lock
generated
@ -1,6 +1,6 @@
|
|||||||
# This file is automatically @generated by Cargo.
|
# This file is automatically @generated by Cargo.
|
||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
version = 3
|
version = 4
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "Inflector"
|
name = "Inflector"
|
||||||
@ -753,9 +753,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cc"
|
name = "cc"
|
||||||
version = "1.2.3"
|
version = "1.2.13"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "27f657647bcff5394bf56c7317665bbf790a137a50eaaa5c6bfbb9e27a518f2d"
|
checksum = "c7777341816418c02e033934a09f20dc0ccaf65a5201ef8a450ae0105a573fda"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"jobserver",
|
"jobserver",
|
||||||
"libc",
|
"libc",
|
||||||
@ -1617,12 +1617,11 @@ name = "frida_core"
|
|||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64 0.22.1",
|
"base64 0.22.1",
|
||||||
|
"cc",
|
||||||
"chrono",
|
"chrono",
|
||||||
"filedescriptor",
|
"filedescriptor",
|
||||||
"futures",
|
"futures",
|
||||||
"libc",
|
|
||||||
"log",
|
"log",
|
||||||
"nix",
|
|
||||||
"rand",
|
"rand",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
|
@ -205,10 +205,18 @@ pub mod desktop {
|
|||||||
use log::info;
|
use log::info;
|
||||||
use tokio::net::UdpSocket;
|
use tokio::net::UdpSocket;
|
||||||
|
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(any(target_os = "linux", target_os = "macos"))]
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
|
|
||||||
|
|
||||||
|
fn cmd(cmd: &str, args: &[&str]) -> String {
|
||||||
|
let ecode = std::process::Command::new(cmd)
|
||||||
|
.args(args)
|
||||||
|
.output();
|
||||||
|
assert!(ecode.is_ok(), "Failed to execte {}", cmd);
|
||||||
|
std::str::from_utf8(&ecode.as_ref().unwrap().stdout).unwrap().to_string()
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
fn configure_routes(endpoint_ip: &str) {
|
fn configure_routes(endpoint_ip: &str) {
|
||||||
let mut if_out = std::process::Command::new("ip")
|
let mut if_out = std::process::Command::new("ip")
|
||||||
@ -306,6 +314,37 @@ pub mod desktop {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "macos")]
|
||||||
|
fn configure_routes(endpoint_ip: &str) {
|
||||||
|
let mut if_out = cmd("route", &["-n", "get", "default"]);
|
||||||
|
let r = std::str::from_utf8(&if_out.as_bytes()).unwrap();
|
||||||
|
|
||||||
|
let mut gateway = None;
|
||||||
|
let mut if_name = None;
|
||||||
|
|
||||||
|
let ui = r.find("gateway: ").unwrap() + 9;
|
||||||
|
let s = &r[ui..];
|
||||||
|
let ei = s.find("\n").unwrap();
|
||||||
|
gateway = Some(&s[..ei]);
|
||||||
|
|
||||||
|
let ui = r.find("interface: ").unwrap() + 11;
|
||||||
|
let s = &r[ui..];
|
||||||
|
let ei = s.find("\n").unwrap();
|
||||||
|
if_name = Some(&s[..ei]);
|
||||||
|
|
||||||
|
info!("Main interface: {:?}", &if_name.unwrap());
|
||||||
|
|
||||||
|
let inter_name = if_name.unwrap();
|
||||||
|
|
||||||
|
info!("Main network interface: {:?}", &gateway.unwrap());
|
||||||
|
|
||||||
|
cmd("route", &["add", "-host", endpoint_ip, &gateway.unwrap()]);
|
||||||
|
|
||||||
|
cmd("route", &["change", "default", "-interface", "utun3"]); // todo: change that
|
||||||
|
|
||||||
|
cmd("route", &["add", "-host", endpoint_ip, &gateway.unwrap()]);
|
||||||
|
}
|
||||||
|
|
||||||
pub struct DesktopClient {
|
pub struct DesktopClient {
|
||||||
pub client_config: ClientConfiguration
|
pub client_config: ClientConfiguration
|
||||||
}
|
}
|
||||||
@ -330,12 +369,15 @@ pub mod desktop {
|
|||||||
let mut client = CoreVpnClient{ client_config: self.client_config.clone(), 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");
|
info!("Platform specific code");
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(any(target_os = "linux", target_os = "macos"))]
|
||||||
{
|
{
|
||||||
let s_a: std::net::SocketAddr = self.client_config.server.endpoint.parse().unwrap();
|
let s_a: std::net::SocketAddr = self.client_config.server.endpoint.parse().unwrap();
|
||||||
configure_routes(&s_a.ip().to_string());
|
configure_routes(&s_a.ip().to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "macos")]
|
||||||
|
sock.connect(&self.client_config.server.endpoint).await.unwrap();
|
||||||
|
|
||||||
client.start(sock, dev_reader, dev_writer, mtu).await;
|
client.start(sock, dev_reader, dev_writer, mtu).await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,12 +25,11 @@ tokio = { workspace = true }
|
|||||||
[target.'cfg(target_os="windows")'.dependencies]
|
[target.'cfg(target_os="windows")'.dependencies]
|
||||||
wintun = "0.5.0"
|
wintun = "0.5.0"
|
||||||
|
|
||||||
[target.'cfg(target_os="macos")'.dependencies]
|
|
||||||
nix = { version = "0.29.0", features = ["socket"] }
|
|
||||||
|
|
||||||
[target.'cfg(target_os="linux")'.dependencies]
|
[target.'cfg(target_os="linux")'.dependencies]
|
||||||
tokio-tun = "0.12.1"
|
tokio-tun = "0.12.1"
|
||||||
|
|
||||||
[target.'cfg(target_os="android")'.dependencies]
|
[target.'cfg(target_os="android")'.dependencies]
|
||||||
libc = "0.2"
|
filedescriptor = "0.8.2"
|
||||||
filedescriptor = "0.8.2"
|
|
||||||
|
[target.'cfg(target_os="macos")'.build-dependencies]
|
||||||
|
cc = "1.2.13"
|
7
frida_core/build.rs
Normal file
7
frida_core/build.rs
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
use cc;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
if cfg!(target_os = "macos") {
|
||||||
|
cc::Build::new().file("src/c/utun.c").compile("utun");
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,3 @@
|
|||||||
//use tokio::fs::File;
|
|
||||||
use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::os::fd::FromRawFd;
|
use std::os::fd::FromRawFd;
|
||||||
@ -6,7 +5,6 @@ use std::os::fd::FromRawFd;
|
|||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::{Write, Read};
|
use std::io::{Write, Read};
|
||||||
|
|
||||||
use libc::fdopen;
|
|
||||||
use std::ffi::CString;
|
use std::ffi::CString;
|
||||||
|
|
||||||
pub fn create(cfg: i32) -> (DeviceReader, DeviceWriter) {
|
pub fn create(cfg: i32) -> (DeviceReader, DeviceWriter) {
|
||||||
|
43
frida_core/src/c/utun.c
Normal file
43
frida_core/src/c/utun.c
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
#include <unistd.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/kern_control.h>
|
||||||
|
#include <net/if_utun.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <sys/kern_event.h>
|
||||||
|
|
||||||
|
int32_t open_utun(uint64_t num) {
|
||||||
|
int err;
|
||||||
|
int fd;
|
||||||
|
struct sockaddr_ctl addr;
|
||||||
|
struct ctl_info info;
|
||||||
|
|
||||||
|
fd = socket(PF_SYSTEM, SOCK_DGRAM, SYSPROTO_CONTROL);
|
||||||
|
if (fd < 0) {
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
memset(&info, 0, sizeof (info));
|
||||||
|
strncpy(info.ctl_name, UTUN_CONTROL_NAME, strlen(UTUN_CONTROL_NAME));
|
||||||
|
err = ioctl(fd, CTLIOCGINFO, &info);
|
||||||
|
if (err < 0) {
|
||||||
|
close(fd);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
addr.sc_id = info.ctl_id;
|
||||||
|
addr.sc_len = sizeof(addr);
|
||||||
|
addr.sc_family = AF_SYSTEM;
|
||||||
|
addr.ss_sysaddr = AF_SYS_CONTROL;
|
||||||
|
addr.sc_unit = num + 1; // utunX where X is sc.sc_unit -1
|
||||||
|
|
||||||
|
err = connect(fd, (struct sockaddr*)&addr, sizeof(addr));
|
||||||
|
if (err < 0) {
|
||||||
|
// this utun is in use
|
||||||
|
close(fd);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
return fd;
|
||||||
|
}
|
@ -3,80 +3,39 @@ use std::{ffi::CString, process::Command};
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use log::info;
|
use log::info;
|
||||||
use nix::errno::Errno;
|
|
||||||
use nix::libc::{connect, sockaddr_ctl, CTLIOCGINFO};
|
|
||||||
use nix::sys::socket::{SockaddrLike, SockaddrStorage, UnixAddr};
|
|
||||||
use nix::{libc::{ctl_info, PF_SYSTEM, SOCK_DGRAM, SYSPROTO_CONTROL}, sys::socket::{socket, AddressFamily, SockFlag, SockProtocol, SockType, sockaddr}};
|
|
||||||
use tokio::fs::File;
|
use tokio::fs::File;
|
||||||
use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
||||||
|
|
||||||
use crate::device::AbstractDevice;
|
use crate::device::AbstractDevice;
|
||||||
|
|
||||||
fn cmd(cmd: &str, args: &[&str]) {
|
extern "C" {
|
||||||
let ecode = Command::new("ip")
|
fn open_utun(num: u64) -> i32;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn cmd(cmd: &str, args: &[&str]) -> String {
|
||||||
|
let ecode = Command::new(cmd)
|
||||||
.args(args)
|
.args(args)
|
||||||
.spawn()
|
.output();
|
||||||
.unwrap()
|
assert!(ecode.is_ok(), "Failed to execte {}", cmd);
|
||||||
.wait()
|
std::str::from_utf8(&ecode.as_ref().unwrap().stdout).unwrap().to_string()
|
||||||
.unwrap();
|
}
|
||||||
assert!(ecode.success(), "Failed to execte {}", cmd);
|
|
||||||
|
fn get_utun() -> (i32, String) {
|
||||||
|
for utun_n in 0..255 {
|
||||||
|
let fd = unsafe { open_utun(utun_n) };
|
||||||
|
if fd >= 0 {
|
||||||
|
let name = format!("utun{}", utun_n);
|
||||||
|
return (fd, name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
panic!("{}", std::io::Error::last_os_error())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create(cfg: AbstractDevice) -> (DeviceReader, DeviceWriter) {
|
pub fn create(cfg: AbstractDevice) -> (DeviceReader, DeviceWriter) {
|
||||||
|
let (fd, if_name) = get_utun();
|
||||||
let fd = socket(
|
let reader = unsafe { File::from_raw_fd(fd) };
|
||||||
AddressFamily::System,
|
let writer = unsafe { File::from_raw_fd(fd) };
|
||||||
SockType::Datagram,
|
cmd("ifconfig", &[&if_name, &cfg.address.unwrap().to_string(), &cfg.destination.unwrap().to_string(), "netmask", &cfg.netmask.unwrap().to_string(), "up"]);
|
||||||
SockFlag::empty(),
|
|
||||||
Some(SockProtocol::KextControl)
|
|
||||||
);
|
|
||||||
|
|
||||||
if let Err(e) = fd {
|
|
||||||
panic!("Unable to open socket! Error: {:?}", e);
|
|
||||||
}
|
|
||||||
|
|
||||||
let fd = fd.unwrap();
|
|
||||||
|
|
||||||
let mut info: ctl_info = unsafe { std::mem::zeroed() };
|
|
||||||
let ctl_name = CString::new("com.apple.net.utun_control").unwrap();
|
|
||||||
ctl_name.as_bytes_with_nul()
|
|
||||||
.iter()
|
|
||||||
.enumerate()
|
|
||||||
.for_each(|(i, &c)| info.ctl_name[i] = c as i8);
|
|
||||||
|
|
||||||
if unsafe { nix::libc::ioctl(fd.as_raw_fd(), CTLIOCGINFO, &mut info) } < 0 {
|
|
||||||
let err = Errno::last();
|
|
||||||
panic!("ioctl CTLIOCGINFO failed: {}", err);
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut sc = sockaddr_ctl {
|
|
||||||
sc_len: std::mem::size_of::<sockaddr_ctl>() as u8,
|
|
||||||
sc_family: nix::libc::AF_SYSTEM as u8,
|
|
||||||
ss_sysaddr: nix::libc::AF_SYS_CONTROL as u16,
|
|
||||||
sc_id: info.ctl_id,
|
|
||||||
sc_unit: 0,
|
|
||||||
sc_reserved: [0; 5]
|
|
||||||
};
|
|
||||||
|
|
||||||
let asc = &sc as *const sockaddr_ctl as *const sockaddr;
|
|
||||||
let f = unsafe { connect(fd.as_raw_fd(), asc, size_of::<sockaddr_ctl>() as u32 ) };
|
|
||||||
|
|
||||||
info!("utun interface created successfully, fd: {:?}", f);
|
|
||||||
|
|
||||||
let mut reader = unsafe { File::from_raw_fd(f) };
|
|
||||||
let mut writer = unsafe { File::from_raw_fd(f) };
|
|
||||||
|
|
||||||
let mut address = cfg.address.unwrap().to_string();
|
|
||||||
address.push_str("/24");
|
|
||||||
|
|
||||||
/*
|
|
||||||
cmd("ip", &["addr", "add", "dev", iface.name(), &address]);
|
|
||||||
cmd("ip", &["link", "set", "up", "dev", iface.name()]);
|
|
||||||
|
|
||||||
let iface = Arc::new(iface);
|
|
||||||
let writer = Arc::clone(&iface);
|
|
||||||
let reader = Arc::clone(&iface);*/
|
|
||||||
|
|
||||||
(DeviceReader {reader}, DeviceWriter {writer})
|
(DeviceReader {reader}, DeviceWriter {writer})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user