use vmi::{
Va, VmiContext, VmiError, VmiOs,
driver::VmiRead,
os::windows::{ArchAdapter, WindowsOs},
utils::reactor::Action,
};
use zerocopy::{FromBytes, IntoBytes};
const NCRYPTBUFFER_SSL_CLIENT_RANDOM: u32 = 20;
#[repr(C)]
#[derive(Debug, Copy, Clone, FromBytes, IntoBytes)]
struct NCryptBuffer {
cbBuffer: u32, BufferType: u32, pvBuffer: u64, }
#[repr(C)]
#[derive(Debug, Copy, Clone, FromBytes, IntoBytes)]
struct NCryptBufferDesc {
ulVersion: u32, cBuffers: u32, pBuffers: u64, }
#[repr(C)]
#[derive(Debug, Copy, Clone, FromBytes, IntoBytes)]
struct SSL_MASTER_KEY {
cbLength: u32, dwMagic: u32, dwProtocol: u32, _pad: u32, pCipherSuite: u64, fClient: i32, rgbMasterKey: [u8; 48], cbMasterKey: u32, }
#[repr(C)]
#[derive(Debug, Copy, Clone, FromBytes, IntoBytes)]
struct NCRYPT_SSL_KEY {
cbLength: u32, dwMagic: u32, dwFlags: u32, RefCount: i32, hSubKey: u64, pProvider: u64, }
pub fn SslGenerateSessionKeys<Driver>(
vmi: &VmiContext<WindowsOs<Driver>>,
) -> Result<Action<<WindowsOs<Driver> as VmiOs>::Architecture>, VmiError>
where
Driver: VmiRead,
Driver::Architecture: ArchAdapter<Driver>,
{
let hMasterKey = vmi.os().function_argument(1)?;
let pParameterList = vmi.os().function_argument(4)?;
let mut client_random = vec![0u8; 32];
let parameter_list = vmi.read_struct::<NCryptBufferDesc>(Va(pParameterList))?;
for i in 0..parameter_list.cBuffers {
let offset = (i as u64) * size_of::<NCryptBuffer>() as u64;
let buffer = vmi.read_struct::<NCryptBuffer>(Va(parameter_list.pBuffers + offset))?;
if buffer.BufferType == NCRYPTBUFFER_SSL_CLIENT_RANDOM {
vmi.read(Va(buffer.pvBuffer), &mut client_random)?;
break;
}
}
let master_key = vmi.read_struct::<NCRYPT_SSL_KEY>(Va(hMasterKey))?;
let subkey = vmi.read_struct::<SSL_MASTER_KEY>(Va(master_key.hSubKey))?;
tracing::info!(
client_random = hex::encode(client_random),
secret = hex::encode(subkey.rgbMasterKey),
);
Ok(Action::default())
}