mirror of
https://github.com/Noratrieb/cluelessh.git
synced 2026-01-14 16:35:06 +01:00
more
This commit is contained in:
parent
f5561004f6
commit
1adf798c5d
5 changed files with 44 additions and 22 deletions
2
Cargo.lock
generated
2
Cargo.lock
generated
|
|
@ -249,6 +249,7 @@ name = "fakessh"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"eyre",
|
"eyre",
|
||||||
|
"hex-literal",
|
||||||
"ssh-transport",
|
"ssh-transport",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tracing",
|
"tracing",
|
||||||
|
|
@ -700,6 +701,7 @@ dependencies = [
|
||||||
"rand",
|
"rand",
|
||||||
"rand_core",
|
"rand_core",
|
||||||
"sha2",
|
"sha2",
|
||||||
|
"subtle",
|
||||||
"tracing",
|
"tracing",
|
||||||
"tracing-subscriber",
|
"tracing-subscriber",
|
||||||
"x25519-dalek",
|
"x25519-dalek",
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
eyre = "0.6.12"
|
eyre = "0.6.12"
|
||||||
|
hex-literal = "0.4.1"
|
||||||
ssh-transport = { path = "./ssh-transport" }
|
ssh-transport = { path = "./ssh-transport" }
|
||||||
|
|
||||||
tokio = { version = "1.39.2", features = ["full"] }
|
tokio = { version = "1.39.2", features = ["full"] }
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ poly1305 = "0.8.0"
|
||||||
rand = "0.8.5"
|
rand = "0.8.5"
|
||||||
rand_core = "0.6.4"
|
rand_core = "0.6.4"
|
||||||
sha2 = "0.10.8"
|
sha2 = "0.10.8"
|
||||||
|
subtle = "2.6.1"
|
||||||
tracing = "0.1.40"
|
tracing = "0.1.40"
|
||||||
tracing-subscriber = { version = "0.3.18", features = ["env-filter"] }
|
tracing-subscriber = { version = "0.3.18", features = ["env-filter"] }
|
||||||
x25519-dalek = "2.0.1"
|
x25519-dalek = "2.0.1"
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
use chacha20::cipher::{KeyInit, KeyIvInit, StreamCipher, StreamCipherSeek};
|
use chacha20::cipher::{KeyInit, KeyIvInit, StreamCipher, StreamCipherSeek};
|
||||||
use poly1305::universal_hash::UniversalHash;
|
|
||||||
use sha2::Digest;
|
use sha2::Digest;
|
||||||
|
use subtle::ConstantTimeEq;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
packet::{Packet, RawPacket},
|
packet::{Packet, RawPacket},
|
||||||
|
|
@ -73,17 +73,18 @@ impl Decryptor for Session {
|
||||||
|
|
||||||
/// Derive a key from the shared secret K and exchange hash H.
|
/// Derive a key from the shared secret K and exchange hash H.
|
||||||
/// <https://datatracker.ietf.org/doc/html/rfc4253#section-7.2>
|
/// <https://datatracker.ietf.org/doc/html/rfc4253#section-7.2>
|
||||||
fn derive_key<const KEY_LEN: usize>(
|
fn derive_key(k: [u8; 32], h: [u8; 32], letter: &str, session_id: [u8; 32]) -> [u8; 64] {
|
||||||
k: [u8; 32],
|
|
||||||
h: [u8; 32],
|
|
||||||
letter: &str,
|
|
||||||
session_id: [u8; 32],
|
|
||||||
) -> [u8; KEY_LEN] {
|
|
||||||
let sha2len = sha2::Sha256::output_size();
|
let sha2len = sha2::Sha256::output_size();
|
||||||
|
let mut output = [0; 64];
|
||||||
|
|
||||||
let mut output = [0; KEY_LEN];
|
//let mut hash = sha2::Sha256::new();
|
||||||
|
//encode_mpint_for_hash(&k, |data| hash.update(data));
|
||||||
|
//hash.update(h);
|
||||||
|
//hash.update(letter.as_bytes());
|
||||||
|
//hash.update(session_id);
|
||||||
|
//output[..sha2len].copy_from_slice(&hash.finalize());
|
||||||
|
|
||||||
for i in 0..(KEY_LEN / sha2len) {
|
for i in 0..(64 / sha2len) {
|
||||||
let mut hash = sha2::Sha256::new();
|
let mut hash = sha2::Sha256::new();
|
||||||
encode_mpint_for_hash(&k, |data| hash.update(data));
|
encode_mpint_for_hash(&k, |data| hash.update(data));
|
||||||
hash.update(h);
|
hash.update(h);
|
||||||
|
|
@ -91,8 +92,9 @@ fn derive_key<const KEY_LEN: usize>(
|
||||||
if i == 0 {
|
if i == 0 {
|
||||||
hash.update(letter.as_bytes());
|
hash.update(letter.as_bytes());
|
||||||
hash.update(session_id);
|
hash.update(session_id);
|
||||||
|
} else {
|
||||||
|
hash.update(&output[..(i * sha2len)]);
|
||||||
}
|
}
|
||||||
hash.update(&output[..(i * sha2len)]);
|
|
||||||
|
|
||||||
output[(i * sha2len)..][..sha2len].copy_from_slice(&hash.finalize())
|
output[(i * sha2len)..][..sha2len].copy_from_slice(&hash.finalize())
|
||||||
}
|
}
|
||||||
|
|
@ -135,6 +137,7 @@ impl SshChaCha20Poly1305 {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn decrypt_len(&self, bytes: &mut [u8], packet_number: u64) {
|
fn decrypt_len(&self, bytes: &mut [u8], packet_number: u64) {
|
||||||
|
eprintln!("encrypted len: {:x?}", &bytes);
|
||||||
// <https://github.com/openssh/openssh-portable/blob/1ec0a64c5dc57b8a2053a93b5ef0d02ff8598e5c/PROTOCOL.chacha20poly1305>
|
// <https://github.com/openssh/openssh-portable/blob/1ec0a64c5dc57b8a2053a93b5ef0d02ff8598e5c/PROTOCOL.chacha20poly1305>
|
||||||
let mut cipher = SshChaCha20::new(&self.header_key, &packet_number.to_be_bytes().into());
|
let mut cipher = SshChaCha20::new(&self.header_key, &packet_number.to_be_bytes().into());
|
||||||
cipher.apply_keystream(bytes);
|
cipher.apply_keystream(bytes);
|
||||||
|
|
@ -156,23 +159,36 @@ impl SshChaCha20Poly1305 {
|
||||||
//)
|
//)
|
||||||
//.map_err(|err| crate::client_error!("failed to decrypt invalid poly1305 MAC: {err}"))?;
|
//.map_err(|err| crate::client_error!("failed to decrypt invalid poly1305 MAC: {err}"))?;
|
||||||
|
|
||||||
let mut cipher = SshChaCha20::new(&self.main_key2, &packet_number.to_be_bytes().into());
|
let mut cipher = <chacha20::ChaCha20Legacy as chacha20::cipher::KeyIvInit>::new(
|
||||||
|
&self.main_key2,
|
||||||
let mut mac = {
|
&packet_number.to_be_bytes().into(),
|
||||||
let mut poly1305_key = [0; poly1305::KEY_SIZE];
|
);
|
||||||
cipher.apply_keystream(&mut poly1305_key);
|
|
||||||
poly1305::Poly1305::new(&poly1305_key.into())
|
|
||||||
};
|
|
||||||
|
|
||||||
let tag_offset = bytes.full_packet().len() - 16;
|
let tag_offset = bytes.full_packet().len() - 16;
|
||||||
let aead_payload = &bytes.full_packet()[..tag_offset];
|
let data_to_mac = &bytes.full_packet()[..tag_offset];
|
||||||
mac.update_padded(aead_payload);
|
eprintln!("data_to_mac: {:x?}", &data_to_mac);
|
||||||
|
|
||||||
|
let mac = {
|
||||||
|
let mut poly1305_key = [0; poly1305::KEY_SIZE];
|
||||||
|
cipher.apply_keystream(&mut poly1305_key);
|
||||||
|
poly1305::Poly1305::new(&poly1305_key.into()).compute_unpadded(data_to_mac)
|
||||||
|
};
|
||||||
|
|
||||||
let read_tag = poly1305::Tag::from_slice(&bytes.full_packet()[tag_offset..]);
|
let read_tag = poly1305::Tag::from_slice(&bytes.full_packet()[tag_offset..]);
|
||||||
|
|
||||||
mac.verify(read_tag)
|
eprintln!("expected MAC: {mac:x?}");
|
||||||
.map_err(|err| crate::client_error!("failed to decrypt invalid poly1305 MAC: {err}"))?;
|
eprintln!("found MAC: {read_tag:x?}");
|
||||||
|
|
||||||
cipher.seek(1);
|
if !bool::from(mac.ct_eq(read_tag)) {
|
||||||
|
return Err(crate::client_error!(
|
||||||
|
"failed to decrypt: invalid poly1305 MAC"
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
//mac.verify(read_tag)
|
||||||
|
// .map_err(|err| crate::client_error!("failed to decrypt invalid poly1305 MAC: {err}"))?;
|
||||||
|
|
||||||
|
cipher.seek(64);
|
||||||
|
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -325,6 +325,8 @@ impl PacketParser {
|
||||||
let packet_length = u32::from_be_bytes(len_to_decrypt);
|
let packet_length = u32::from_be_bytes(len_to_decrypt);
|
||||||
let packet_length = packet_length.try_into().unwrap();
|
let packet_length = packet_length.try_into().unwrap();
|
||||||
|
|
||||||
|
dbg!(packet_length);
|
||||||
|
|
||||||
self.packet_length = Some(packet_length);
|
self.packet_length = Some(packet_length);
|
||||||
|
|
||||||
// We have the data.
|
// We have the data.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue