前回のプログラムでカリグラム的なことをしてみました。
ステルス・スキャンなので「隠」の一字です。
const TO:u64=5000;const M:[&str;4]=["open","closed","timeout","unknown"];use pnet::{
ipnetwork::IpNetwork as IN,packet::{ip::IpNextHeaderProtocols::Tcp, ipv4::Ipv4Packet
as I4P, Packet, tcp :: { ipv4_checksum as ic, MutableTcpPacket as MTP,
TcpFlags:: {ACK, RST, SYN}, TcpOption as TOP, TcpPacket as TP},ethernet
:: {EtherTypes as ET, EthernetPacket as EP}}, datalink::{Channel::
Ethernet as E,NetworkInterface as NI, {channel as chn, interfaces as
ifcs }}, transport:: { transport_channel as tc, TransportChannelType::
Layer4 as L4,TransportProtocol::Ipv4}};use rand ::Rng; use std::{net::{
IpAddr as IA, Ipv4Addr as I4A},str:: FromStr, sync::mpsc:: {
channel as ch, RecvError as MRE, RecvTimeoutError as MRTE},
thread::{ sleep,spawn},time ::Duration as D};const SA:u8=SYN
+ACK;const RA:u8=RST+ACK;fn main(){if let Err(e)=run(){eprintln
!( "[Error] {:?}",e) }}fn run()->Result<(),ME>{let args:Vec<
String >=std::env::args() .collect();if args.len()<2{return Ok(
eprintln !( "Usage: {} interface ip:port",args[0
])) ;}if args.len()<3 {return Err(ME::TFAE);}let
ifcn= &args [1];let tgt:&str=& args[2 ];Ok(pr(tgt,prc(
ifcn.to_string (),tgt )?))}fn pr (tgt:&str ,ff:u8){println
!("[Result]"); println !("{}: {}" ,tgt,M[ match ff{SA=>0
,RA=>1,0=>2,_ =>3,}]) ;}fn prc (ifcn: String,tgt:&str
)->Result<u8, ME>{let(ri ,rp)=sip (tgt)? ;let r=ifcs().
into_iter(). find(|ifc |ifc. name== ifcn);if r.is_none
(){return Err (ME::UIE); }let ifc=r .unwrap();println
!( "Interface: {}" ,ifc.name );let mut li:Option<I4A>
=None;for ip in&ifc.ips{if let IN:: V4(v4 )=ip{li=Some(v4.ip(
));break;}} if li.is_none( ){return Err (ME::LIE);}let li=li.
unwrap();let mut rng=rand:: thread_rng( );let lp=rng.gen_range(
32768..=60999 );let ff=SYN; let seq:u32= rand::random();let ack:u32
=0; println !("Local: {}:{}",li ,lp); println!("Remote: {}:{}",ri
,rp );s_r (ifc,lp,rp,li,ri,ff,seq,ack) }fn s_r(ifc:NI,lp:u16,rp:
u16 ,li:I4A ,ri:I4A,ff:u8,seq:u32,ack :u32,)->Result<u8,ME>
{let (mut tx,_)=tc(4096,L4( Ipv4(Tcp)))?;let
mut bb:[u8 ;24]=[0;24];let p=th(&mut bb,lp
,rp ,li,ri ,ff,seq,ack)? ;let( t,r)=ch(); let
h = spawn ( move||{t.send (match recv (ifc,lp,rp,li
,ri ){Err(e) =>{eprintln !("[Error] {:?}" ,e);0u8}Ok(ff
)=> ff, } ). unwrap();}); sleep(D::from_millis (100)); tx.
send_to (p,IA:: V4(ri))?; pth( "[Sent]", ff, seq, ack,1000);Ok(
match r.recv_timeout (D:: from_millis
(TO )){Ok(f)=> {h.join ().unwrap();f
}_=> 0,})} fn th( bb:&mut[u8],lp
:u16 ,rp :u16,li :I4A,ri:I4A,ff
:u8 ,seq:u32 ,ack:u32,) ->Result<MTP,ME
>{let pkt = MTP::new(bb); if pkt.is_none( ){return Err(ME
:: MTPE);}let mut pkt=pkt.unwrap();pkt.set_flags(ff );pkt.set_source
(lp) ;pkt.set_destination(rp);pkt.set_window(1000); pkt.set_data_offset
(6 ) ; pkt . set_acknowledgement( ack ); pkt.set_sequence(seq);
pkt .set_options( &[TOP::mss(1460) ]);pkt.set_checksum
(ic (&pkt.to_immutable(),&li,&ri)) ;Ok(pkt)}fn recv(ifc
:NI ,lp:u16,rp:u16,li:I4A,ri:I4A )->Result<u8,ME>{let
mut ff=0u8;if let E(_,mut rx)= chn(&ifc,Default::default
() )? {loop{let bytes=rx.next ()?;let frame=EP::new(bytes);
if frame.is_none(){continue;}let frame = frame.unwrap();if frame.get_ethertype
() !=ET::Ipv4{continue;} let ipv4=I4P::new(frame.payload()); if ipv4.is_none()
{ continue;} let ipv4=ipv4.unwrap(); if ipv4.get_source()!=ri || ipv4
. get_destination()!=li{continue;}if ipv4.get_next_level_protocol (
) !=Tcp{continue;}let tcp=TP ::new(ipv4 .payload()
); if tcp.is_none(){continue ;}let tcp =tcp.unwrap
() ;if tcp.get_source()!=rp ||tcp. get_destination
( )!=lp{continue;}ff=tcp. get_flags ();let seq=tcp
. get_sequence();let ack=tcp . get_acknowledgement
( );let win=tcp. get_window ();pth( "[Received]",ff,
seq ,ack,win);break ; }}Ok(ff )}fn pth (tag:&str,ff:u8,seq :
u32 ,ack:u32,win:u16 ){ println!("{}", tag);println!("Flags: {}"
, conv(ff));println !( "Seq No: {}" ,seq); println
! ("Ack No: {}" ,ack) ;println!( "Window: {}",win)
; }const F:[&str ;8]=[ "FIN","SYN","RST", "PSH","ACK","URG"
, "ECE","CWR"];fn conv( ff:u8)->String{let mut r=vec![];let
mut a=0;while a <8{let b=2u32.pow(a as u32);if(ff as
u32)&b!=0{r.push (F[a] );}a+=1;}r.join (",")}fn sip
(s:&str)->Result <(I4A ,u16),ME>{let a:Vec<&str>
=s.split(':'). collect ();if a.len()!=2
{ return Err(ME::TE );}if let Ok(ip
) =I4A::from_str(a[0 ]){if let Ok(port
)= a[1].parse(){return Ok((ip,port ));}}Err(
ME:: TE)}#[derive(thiserror ::Error,Debug )]enum ME{
#[ error("IOE")]IOE(#[from]std::io::Error), #[error("MTPE")]
MTPE,#[error("TFAE")]TFAE,#[error("TE")]TE,#[error("UIE")]UIE,#[error("LIE")]LIE, #[
error("TOE")]TOE(#[from]MRTE),#[error("RE")]RE(#[from]MRE),}/*by mekamaru(@bunji2)*/
内容はほぼ変えず、使うモジュール名の短縮化、変数名の短縮化などを行いました。
Tシャツにするとこんな感じ。。。
厳しいか。。。