Skip to content

Commit 600d6e5

Browse files
committed
Fix issue #2 and #6
1 parent b4804d1 commit 600d6e5

File tree

8 files changed

+103
-27
lines changed

8 files changed

+103
-27
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
### 0.1.1 (2020-04-11)
2+
#### Features
3+
* Remove dependency of rust-crypto
4+
* Fix parameter name
5+
* Fix overflow in packet computation
6+
17
### 0.1.0 (2020-04-11)
28
#### Features
39
* Initial release

Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ md4 = "^0.8"
3535
hmac = "^0.7"
3636
md-5 = "^0.8"
3737
rand = "^0.7"
38-
rust-crypto = "^0.2"
3938
num-bigint = "^0.2"
4039
x509-parser = "0.6.5"
4140
num_enum = "0.4.3"

src/bin/mstsc-rs.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,7 @@ fn to_scancode(key: Key) -> u16 {
231231

232232
/// Create a tcp stream from main args
233233
fn tcp_from_args(args: &ArgMatches) -> RdpResult<TcpStream> {
234-
let ip = args.value_of("target").expect("You need to provide a target argument");
234+
let ip = args.value_of("host").expect("You need to provide a target argument");
235235
let port = args.value_of("port").unwrap_or_default();
236236

237237
// TCP connection
@@ -449,10 +449,10 @@ fn main() {
449449
.version("0.1.0")
450450
.author("Sylvain Peyrefitte <citronneur@gmail.com>")
451451
.about("Secure Remote Desktop Client in RUST")
452-
.arg(Arg::with_name("target")
453-
.long("target")
452+
.arg(Arg::with_name("host")
453+
.long("host")
454454
.takes_value(true)
455-
.help("Target IP of the server"))
455+
.help("host IP of the target machine"))
456456
.arg(Arg::with_name("port")
457457
.long("port")
458458
.takes_value(true)
@@ -469,7 +469,7 @@ fn main() {
469469
.default_value("600")
470470
.help("Screen height"))
471471
.arg(Arg::with_name("domain")
472-
.long("dom")
472+
.long("domain")
473473
.takes_value(true)
474474
.default_value("")
475475
.help("Windows domain"))
@@ -479,7 +479,7 @@ fn main() {
479479
.default_value("")
480480
.help("Username"))
481481
.arg(Arg::with_name("password")
482-
.long("pass")
482+
.long("password")
483483
.takes_value(true)
484484
.default_value("")
485485
.help("Password"))
@@ -506,7 +506,7 @@ fn main() {
506506
.help("Check the target SSL certificate"))
507507
.arg(Arg::with_name("disable_nla")
508508
.long("ssl")
509-
.help("Disable Netwoek Level Authentication and only use SSL"))
509+
.help("Disable Network Level Authentication and only use SSL"))
510510
.arg(Arg::with_name("name")
511511
.long("name")
512512
.default_value("mstsc-rs")

src/core/tpkt.rs

Lines changed: 50 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -105,17 +105,17 @@ impl<S: Read + Write> Client<S> {
105105
/// panic!("unexpected result")
106106
/// }
107107
///
108-
/// tpkt = tpkt::Client::new(link::Link::new(link::Stream::Raw(Cursor::new(vec![0, 6, 0, 0, 0, 0]))));
108+
/// tpkt = tpkt::Client::new(link::Link::new(link::Stream::Raw(Cursor::new(vec![0, 7, 0, 0, 0, 0, 0]))));
109109
/// if let tpkt::Payload::FastPath(_, c) = tpkt.read().unwrap() {
110-
/// assert_eq!(c.into_inner(), vec![0, 0, 0, 0])
110+
/// assert_eq!(c.into_inner(), vec![0, 0, 0, 0, 0])
111111
/// }
112112
/// else {
113113
/// panic!("unexpected result")
114114
/// }
115115
///
116-
/// tpkt = tpkt::Client::new(link::Link::new(link::Stream::Raw(Cursor::new(vec![0, 0x80, 7, 0, 0, 0, 0]))));
116+
/// tpkt = tpkt::Client::new(link::Link::new(link::Stream::Raw(Cursor::new(vec![0, 0x80, 8, 0, 0, 0, 0, 0]))));
117117
/// if let tpkt::Payload::FastPath(_, c) = tpkt.read().unwrap() {
118-
/// assert_eq!(c.into_inner(), vec![0, 0, 0, 0])
118+
/// assert_eq!(c.into_inner(), vec![0, 0, 0, 0, 0])
119119
/// }
120120
/// else {
121121
/// panic!("unexpected result")
@@ -136,9 +136,15 @@ impl<S: Read + Write> Client<S> {
136136
let mut size = U16::BE(0);
137137
size.read(&mut buffer)?;
138138

139-
// now wait for body
140-
Ok(Payload::Raw(Cursor::new(self.transport.read(size.inner() as usize - 4)?)))
141-
139+
// Minimal size must be 7
140+
// https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpbcgr/18a27ef9-6f9a-4501-b000-94b1fe3c2c10
141+
if size.inner() < 7 {
142+
Err(Error::RdpError(RdpError::new(RdpErrorKind::InvalidSize, "Invalid minimal size for TPKT")))
143+
}
144+
else {
145+
// now wait for body
146+
Ok(Payload::Raw(Cursor::new(self.transport.read(size.inner() as usize - 4)?)))
147+
}
142148
} else {
143149
// fast path
144150
let sec_flag = (action >> 6) & 0x3;
@@ -147,12 +153,20 @@ impl<S: Read + Write> Client<S> {
147153
if short_length & 0x80 != 0 {
148154
let mut hi_length: u8 = 0;
149155
hi_length.read(&mut Cursor::new(self.transport.read(1)?))?;
150-
let length :u16 = ((short_length & !0x80) as u16) << 8;
156+
let length: u16 = ((short_length & !0x80) as u16) << 8;
151157
let length = length | hi_length as u16;
152-
Ok(Payload::FastPath(sec_flag, Cursor::new(self.transport.read(length as usize - 3)?)))
158+
if length < 7 {
159+
Err(Error::RdpError(RdpError::new(RdpErrorKind::InvalidSize, "Invalid minimal size for TPKT")))
160+
} else {
161+
Ok(Payload::FastPath(sec_flag, Cursor::new(self.transport.read(length as usize - 3)?)))
162+
}
153163
}
154164
else {
155-
Ok(Payload::FastPath(sec_flag, Cursor::new(self.transport.read(short_length as usize - 2)?)))
165+
if short_length < 7 {
166+
Err(Error::RdpError(RdpError::new(RdpErrorKind::InvalidSize, "Invalid minimal size for TPKT")))
167+
} else {
168+
Ok(Payload::FastPath(sec_flag, Cursor::new(self.transport.read(short_length as usize - 2)?)))
169+
}
156170
}
157171
}
158172
}
@@ -210,6 +224,7 @@ mod test {
210224
use super::*;
211225
use std::io::Cursor;
212226
use model::data::{U32, DataType};
227+
use model::link::Stream;
213228

214229
/// Test the tpkt header type in write context
215230
#[test]
@@ -233,4 +248,29 @@ mod test {
233248
assert_eq!(cast!(DataType::U16, message["size"]).unwrap(), 8);
234249
assert_eq!(cast!(DataType::U8, message["action"]).unwrap(), Action::FastPathActionX224 as u8);
235250
}
251+
252+
fn process(data: &[u8]) {
253+
let cur = Cursor::new(data.to_vec());
254+
let link = Link::new(Stream::Raw(cur));
255+
let mut client = Client::new(link);
256+
let _ = client.read();
257+
}
258+
259+
#[test]
260+
fn test_tpkt_size_overflow_case_1() {
261+
let buf = b"\x00\x00\x03\x00\x00\x00";
262+
process(buf);
263+
}
264+
265+
#[test]
266+
fn test_tpkt_size_overflow_case_2() {
267+
let buf = b"\x00\x80\x00\x00\x00\x00";
268+
process(buf);
269+
}
270+
271+
#[test]
272+
fn test_tpkt_size_overflow_case_3() {
273+
let buf = b"\x03\xe8\x00\x00\x80\x00";
274+
process(buf);
275+
}
236276
}

src/lib.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ extern crate md4;
66
extern crate hmac;
77
extern crate md5;
88
extern crate rand;
9-
extern crate crypto;
109
extern crate num_bigint;
1110
extern crate x509_parser;
1211
extern crate num_enum;

src/nla/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@ pub mod asn1;
33
pub mod cssp;
44
pub mod ntlm;
55
pub mod sspi;
6+
pub mod rc4;

src/nla/ntlm.rs

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,7 @@ use md4::{Md4, Digest};
77
use hmac::{Hmac, Mac};
88
use md5::{Md5};
99
use model::rnd::{random};
10-
use crypto::rc4::{Rc4};
11-
use crypto::symmetriccipher::SynchronousStreamCipher;
10+
use nla::rc4::{Rc4};
1211
use num_enum::TryFromPrimitive;
1312
use std::convert::TryFrom;
1413

@@ -651,9 +650,8 @@ impl NTLMv2SecurityInterface {
651650
///
652651
/// # Example
653652
/// ```no_run
654-
/// extern crate crypto;
655653
/// use rdp::nla::ntlm::NTLMv2SecurityInterface;
656-
/// use crypto::rc4::Rc4;
654+
/// use rdp::nla::rc4::Rc4;
657655
/// let interface = NTLMv2SecurityInterface::new(Rc4::new(b"encrypt"), Rc4::new(b"decrypt"), b"signing".to_vec(), b"verify".to_vec());
658656
/// ```
659657
pub fn new(encrypt: Rc4, decrypt: Rc4, signing_key: Vec<u8>, verify_key: Vec<u8>) -> Self {
@@ -673,9 +671,8 @@ impl GenericSecurityService for NTLMv2SecurityInterface {
673671
///
674672
/// # Example
675673
/// ```
676-
/// extern crate crypto;
677674
/// use rdp::nla::ntlm::NTLMv2SecurityInterface;
678-
/// use crypto::rc4::Rc4;
675+
/// use rdp::nla::rc4::Rc4;
679676
/// use rdp::nla::sspi::GenericSecurityService;
680677
/// let mut interface = NTLMv2SecurityInterface::new(Rc4::new(b"encrypt"), Rc4::new(b"decrypt"), b"signing".to_vec(), b"verify".to_vec());
681678
/// assert_eq!(interface.gss_wrapex(b"foo").unwrap(), [1, 0, 0, 0, 142, 146, 37, 160, 247, 244, 100, 58, 0, 0, 0, 0, 87, 164, 208]);
@@ -694,9 +691,8 @@ impl GenericSecurityService for NTLMv2SecurityInterface {
694691
///
695692
/// # Example
696693
/// ```
697-
/// extern crate crypto;
698694
/// use rdp::nla::ntlm::NTLMv2SecurityInterface;
699-
/// use crypto::rc4::Rc4;
695+
/// use rdp::nla::rc4::Rc4;
700696
/// use rdp::nla::sspi::GenericSecurityService;
701697
/// let mut interface = NTLMv2SecurityInterface::new(Rc4::new(b"decrypt"), Rc4::new(b"encrypt"), b"verify".to_vec(), b"signing".to_vec());
702698
/// assert_eq!(interface.gss_unwrapex(&vec![1, 0, 0, 0, 142, 146, 37, 160, 247, 244, 100, 58, 0, 0, 0, 0, 87, 164, 208]).unwrap(), b"foo");

src/nla/rc4.rs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
pub struct Rc4 {
2+
i: u8,
3+
j: u8,
4+
state: [u8; 256]
5+
}
6+
7+
impl Rc4 {
8+
pub fn new(key: &[u8]) -> Rc4 {
9+
assert!(key.len() >= 1 && key.len() <= 256);
10+
let mut rc4 = Rc4 { i: 0, j: 0, state: [0; 256] };
11+
for (i, x) in rc4.state.iter_mut().enumerate() {
12+
*x = i as u8;
13+
}
14+
let mut j: u8 = 0;
15+
for i in 0..256 {
16+
j = j.wrapping_add(rc4.state[i]).wrapping_add(key[i % key.len()]);
17+
rc4.state.swap(i, j as usize);
18+
}
19+
rc4
20+
}
21+
fn next(&mut self) -> u8 {
22+
self.i = self.i.wrapping_add(1);
23+
self.j = self.j.wrapping_add(self.state[self.i as usize]);
24+
self.state.swap(self.i as usize, self.j as usize);
25+
let k = self.state[(self.state[self.i as usize].wrapping_add(self.state[self.j as usize])) as usize];
26+
k
27+
}
28+
29+
pub fn process(&mut self, input: &[u8], output: &mut [u8]) {
30+
assert!(input.len() == output.len());
31+
for (x, y) in input.iter().zip(output.iter_mut()) {
32+
*y = *x ^ self.next();
33+
}
34+
}
35+
}

0 commit comments

Comments
 (0)