@@ -7,7 +7,7 @@ use std::io::prelude::*;
77use std:: io:: BufWriter ;
88use std:: io:: Cursor ;
99use structopt:: StructOpt ;
10- use pcap:: Capture ;
10+ use pcap:: { Capture , Linktype , Savefile } ;
1111use gamestreaming:: pnet:: util:: MacAddr ;
1212use gamestreaming:: pnet:: packet:: ethernet:: { EtherTypes , EthernetPacket } ;
1313use gamestreaming:: pnet:: packet:: ipv4:: Ipv4Packet ;
@@ -23,6 +23,8 @@ use gamestreaming::teredo::{Teredo, TeredoEndpoint};
2323type Error = Box < dyn std:: error:: Error > ;
2424type Result < T > = std:: result:: Result < T , Error > ;
2525
26+ const AUTH_TAG_LEN : usize = 16 ;
27+
2628#[ derive( Debug ) ]
2729struct RtpPacketResult {
2830 is_client : bool ,
@@ -194,7 +196,7 @@ struct Opt {
194196 srtp_key : Option < String > ,
195197
196198 #[ structopt( long) ]
197- dump_video : Option < PathBuf > ,
199+ decrypt_pcap : Option < PathBuf > ,
198200}
199201
200202fn main ( ) {
@@ -207,6 +209,8 @@ fn main() {
207209
208210 let mut parser = PcapParser :: new ( ) ;
209211
212+ // Initialize Crypto context
213+ // If no key is provided, use dummy key
210214 let mut crypto_context: crypto:: MsSrtpCryptoContext = {
211215 if let Some ( key) = opt. srtp_key {
212216 crypto:: MsSrtpCryptoContext :: from_base64 ( & key)
@@ -218,25 +222,28 @@ fn main() {
218222 }
219223 } ;
220224
221- let fhandle = {
222- match opt. dump_video {
223- Some ( filepath) => Some ( File :: create ( filepath) . expect ( "Failed to create file for video-dump" ) ) ,
224- None => None
225- }
226- } ;
225+ // Only used for writing decrypted pcap
226+ let capture_out = Capture :: dead ( Linktype :: ETHERNET )
227+ . expect ( "Failed to create pcap OUT handle" ) ;
227228
228- let mut buf_writer = {
229- match fhandle {
230- Some ( handle) => Some ( BufWriter :: new ( handle) ) ,
231- None => None ,
232- }
229+ // Open handle for writing decrypted pcap
230+ let mut pcap_out_handle = match opt. decrypt_pcap {
231+ Some ( filepath) => {
232+ let savefile = capture_out. savefile ( filepath)
233+ . expect ( "Failed to create Savefile pcap OUT instance" ) ;
234+
235+ Some ( savefile)
236+ } ,
237+ None => None
233238 } ;
234239
235- while let Ok ( packet) = cap. next ( ) {
236- if let Ok ( rtp_response) = parser. handle_packet ( & packet. data ) {
240+ while let Ok ( pcap_packet) = cap. next ( ) {
241+ if let Ok ( rtp_response) = parser. handle_packet ( & pcap_packet. data ) {
242+ // Handle RTP packet
237243 let packet = rtp_response. packet ;
238244
239- let decryption_result = {
245+ // Decrypt RTP packet
246+ let plaintext = {
240247 if rtp_response. is_client {
241248 // println!("CLIENT -> XBOX");
242249 crypto_context. decrypt_rtp ( & packet)
@@ -245,26 +252,37 @@ fn main() {
245252 // println!("XBOX -> CLIENT");
246253 crypto_context. decrypt_rtp_as_host ( & packet)
247254 }
248- } ;
255+ } . expect ( "Failed to decrypt RTP" ) ;
249256
250- if let Ok ( plaintext ) = decryption_result {
251- let mut reader = BufReader :: new ( & plaintext [ .. ] ) ;
252- if let Ok ( rtp_packet ) = rtp :: packet :: Packet :: unmarshal ( & mut reader ) {
253- packets :: parse_rtp_packet ( & rtp_packet ) ;
254- /*
255- if let Some(ref mut writer) = buf_writer {
256- if rtp_packet.header.ssrc == 1026 && rtp_packet.payload[0xC] == 0x4 {
257- let frame = packets::VideoFrame::unpack(&rtp_packet.payload[..20].try_into().unwrap()). expect("Failed to read VideoFrame ");
258- println!("VideoFrame: {:?}", frame);
259- // writer.write(&vframe). expect("Failed to write");
257+ match pcap_out_handle . as_mut ( ) {
258+ Some ( savefile ) => {
259+ // Assemble plaintext packet payload
260+ let datasize_until_ciphertext = pcap_packet . data . len ( ) - ( plaintext . len ( ) + AUTH_TAG_LEN ) ;
261+
262+ let mut plaintext_eth_data : Vec < u8 > = vec ! [ ] ;
263+ plaintext_eth_data . write ( & pcap_packet . data [ ..datasize_until_ciphertext ] )
264+ . expect ( "Failed to write packet data until ciphertext " ) ;
265+ plaintext_eth_data . write ( & plaintext )
266+ . expect ( "Failed to write decrypted ciphertext portion " ) ;
260267
261- //return;
262- }
268+ // Save decrypted RTP packet to pcap out
269+ savefile. write ( & pcap:: Packet :: new ( & pcap_packet. header , & plaintext_eth_data) ) ;
270+ } ,
271+ None => {
272+ // Parse & print packet info
273+ let mut reader = BufReader :: new ( & plaintext[ ..] ) ;
274+ if let Ok ( rtp_packet) = rtp:: packet:: Packet :: unmarshal ( & mut reader) {
275+ packets:: parse_rtp_packet ( & rtp_packet) ;
263276 }
264- */
265277 }
266- } else {
267- println ! ( "Failed to decrypt RTP" ) ;
278+ }
279+ } else {
280+ // Write non-RTP packet as-is
281+ match pcap_out_handle. as_mut ( ) {
282+ Some ( savefile) => {
283+ savefile. write ( & pcap_packet)
284+ } ,
285+ None => { } ,
268286 }
269287 }
270288 }
0 commit comments