use crate::windows::constants::*;
use crate::emu::Emu;
use super::sync;
pub fn nt_query_multiple_value_key(emu: &mut Emu) {
let key_handle = emu.regs().rcx;
let value_entries = emu.regs().rdx;
let entry_count = emu.regs().r8;
let value_buffer = emu.regs().r9;
let rsp = emu.regs().rsp;
let buf_len_ptr = emu.maps.read_qword(rsp + 0x28).unwrap_or(0);
let req_buf_len_ptr = emu.maps.read_qword(rsp + 0x30).unwrap_or(0);
log_orange!(
emu,
"syscall 0x{:x}: NtQueryMultipleValueKey handle: 0x{:x} entries: 0x{:x} count: {} buf: 0x{:x}",
WIN64_NTQUERYMULTIPLEVALUEKEY,
key_handle,
value_entries,
entry_count,
value_buffer,
);
if buf_len_ptr != 0 && emu.maps.is_mapped(buf_len_ptr) {
let _ = emu.maps.write_dword(buf_len_ptr, 0);
}
if req_buf_len_ptr != 0 && emu.maps.is_mapped(req_buf_len_ptr) {
let _ = emu.maps.write_dword(req_buf_len_ptr, 0);
}
emu.regs_mut().rax = STATUS_SUCCESS;
}
pub fn nt_create_directory_object(emu: &mut Emu) {
let handle_out = emu.regs().rcx;
let desired_access = emu.regs().rdx;
let object_attributes = emu.regs().r8;
let dir_name = read_object_attributes_name(emu, object_attributes);
log_orange!(
emu,
"syscall 0x{:x}: NtCreateDirectoryObject out: 0x{:x}, access: 0x{:x}, name: \"{}\"",
WIN64_NTCREATEDIRECTORYOBJECT,
handle_out,
desired_access,
dir_name,
);
if handle_out == 0 || !emu.maps.is_mapped(handle_out) {
emu.regs_mut().rax = STATUS_INVALID_PARAMETER;
return;
}
let h = sync::next_handle();
let _ = emu.maps.write_qword(handle_out, h);
emu.regs_mut().rax = STATUS_SUCCESS;
}
pub fn nt_open_directory_object(emu: &mut Emu) {
let handle_out = emu.regs().rcx;
let desired_access = emu.regs().rdx;
let object_attributes = emu.regs().r8;
let dir_name = read_object_attributes_name(emu, object_attributes);
log_orange!(
emu,
"syscall 0x{:x}: NtOpenDirectoryObject out: 0x{:x}, access: 0x{:x}, name: \"{}\"",
WIN64_NTOPENDIRECTORYOBJECT,
handle_out,
desired_access,
dir_name,
);
if handle_out == 0 || !emu.maps.is_mapped(handle_out) {
emu.regs_mut().rax = STATUS_INVALID_PARAMETER;
return;
}
let h = sync::next_handle();
let _ = emu.maps.write_qword(handle_out, h);
let lower = dir_name.to_lowercase();
if lower == "\\knowndlls" || lower == "\\knowndlls32" {
log::trace!("NtOpenDirectoryObject: tracking KnownDlls dir handle 0x{:x} ({})", h, dir_name);
emu.known_dll_dir_handles.insert(h);
}
emu.regs_mut().rax = STATUS_SUCCESS;
}
pub fn nt_open_key(emu: &mut Emu) {
let handle_out = emu.regs().rcx;
let desired_access = emu.regs().rdx;
let object_attributes = emu.regs().r8;
let key_name = read_object_attributes_name(emu, object_attributes);
log_orange!(
emu,
"syscall 0x{:x}: NtOpenKey out: 0x{:x}, access: 0x{:x}, name: \"{}\"",
WIN64_NTOPENKEY,
handle_out,
desired_access,
key_name
);
if handle_out == 0 || !emu.maps.is_mapped(handle_out) {
emu.regs_mut().rax = STATUS_INVALID_PARAMETER;
return;
}
let h = sync::next_handle();
emu.maps.write_qword(handle_out, h);
emu.regs_mut().rax = STATUS_SUCCESS;
}
pub fn nt_open_key_ex(emu: &mut Emu) {
let handle_out = emu.regs().rcx;
let desired_access = emu.regs().rdx;
let object_attributes = emu.regs().r8;
let key_name = read_object_attributes_name(emu, object_attributes);
log_orange!(
emu,
"syscall 0x{:x}: NtOpenKeyEx out: 0x{:x}, access: 0x{:x}, name: \"{}\"",
WIN64_NTOPENKEYEX,
handle_out,
desired_access,
key_name
);
if handle_out == 0 || !emu.maps.is_mapped(handle_out) {
emu.regs_mut().rax = STATUS_INVALID_PARAMETER;
return;
}
let h = sync::next_handle();
emu.maps.write_qword(handle_out, h);
emu.regs_mut().rax = STATUS_SUCCESS;
}
pub fn nt_open_key_transacted(emu: &mut Emu) {
let handle_out = emu.regs().rcx;
let desired_access = emu.regs().rdx;
let object_attributes = emu.regs().r8;
let key_name = read_object_attributes_name(emu, object_attributes);
log_orange!(
emu,
"syscall 0x{:x}: NtOpenKeyTransacted out: 0x{:x}, access: 0x{:x}, name: \"{}\"",
WIN64_NTOPENKEYTRANSACTED,
handle_out,
desired_access,
key_name
);
if handle_out == 0 || !emu.maps.is_mapped(handle_out) {
emu.regs_mut().rax = STATUS_INVALID_PARAMETER;
return;
}
let h = sync::next_handle();
emu.maps.write_qword(handle_out, h);
emu.regs_mut().rax = STATUS_SUCCESS;
}
pub fn nt_open_key_transacted_ex(emu: &mut Emu) {
let handle_out = emu.regs().rcx;
let desired_access = emu.regs().rdx;
let object_attributes = emu.regs().r8;
let key_name = read_object_attributes_name(emu, object_attributes);
log_orange!(
emu,
"syscall 0x{:x}: NtOpenKeyTransactedEx out: 0x{:x}, access: 0x{:x}, name: \"{}\"",
WIN64_NTOPENKEYTRANSACTEDEX,
handle_out,
desired_access,
key_name
);
if handle_out == 0 || !emu.maps.is_mapped(handle_out) {
emu.regs_mut().rax = STATUS_INVALID_PARAMETER;
return;
}
let h = sync::next_handle();
emu.maps.write_qword(handle_out, h);
emu.regs_mut().rax = STATUS_SUCCESS;
}
pub fn nt_query_value_key(emu: &mut Emu) {
let key_handle = emu.regs().rcx;
let value_name_ptr = emu.regs().rdx;
let info_class = emu.regs().r8;
let info_buf = emu.regs().r9;
let rsp = emu.regs().rsp;
let length = emu.maps.read_qword(rsp + 0x28).unwrap_or(0);
let result_length = emu.maps.read_qword(rsp + 0x30).unwrap_or(0);
let value_name = read_unicode_string(emu, value_name_ptr);
log_orange!(
emu,
"syscall 0x{:x}: NtQueryValueKey handle: 0x{:x}, value: \"{}\", class: 0x{:x}, buf: 0x{:x}, len: 0x{:x}",
WIN64_NTQUERYVALUEKEY,
key_handle,
value_name,
info_class,
info_buf,
length
);
if result_length != 0 && emu.maps.is_mapped(result_length) {
emu.maps.write_dword(result_length, 0);
}
emu.regs_mut().rax = STATUS_OBJECT_NAME_NOT_FOUND;
}
pub fn nt_query_open_subkeys_ex(emu: &mut Emu) {
let object_attributes = emu.regs().rcx;
let buffer_length = emu.regs().rdx;
let buffer = emu.regs().r8;
let required_size = emu.regs().r9;
let key_name = read_object_attributes_name(emu, object_attributes);
log_orange!(
emu,
"syscall 0x{:x}: NtQueryOpenSubKeysEx key: \"{}\", buf: 0x{:x}, len: 0x{:x}",
WIN64_NTQUERYOPENSUBKEYSEX,
key_name,
buffer,
buffer_length,
);
const NEEDED: u32 = 4;
if required_size != 0 && emu.maps.is_mapped(required_size) {
let _ = emu.maps.write_dword(required_size, NEEDED);
}
if buffer == 0 || buffer_length < NEEDED as u64 {
emu.regs_mut().rax = STATUS_BUFFER_TOO_SMALL;
return;
}
if !emu.maps.is_mapped(buffer) {
emu.regs_mut().rax = STATUS_ACCESS_VIOLATION;
return;
}
let _ = emu.maps.write_dword(buffer, 0);
emu.regs_mut().rax = STATUS_SUCCESS;
}
fn read_unicode_string(emu: &Emu, addr: u64) -> String {
if addr == 0 || !emu.maps.is_mapped(addr) {
return String::new();
}
let _len = emu.maps.read_word(addr).unwrap_or(0);
let buf = emu.maps.read_qword(addr + 8).unwrap_or(0);
if buf == 0 || !emu.maps.is_mapped(buf) {
return String::new();
}
emu.maps.read_wide_string(buf)
}
fn read_object_attributes_name(emu: &Emu, addr: u64) -> String {
if addr == 0 || !emu.maps.is_mapped(addr) {
return String::new();
}
let object_name_ptr = emu.maps.read_qword(addr + 0x10).unwrap_or(0);
read_unicode_string(emu, object_name_ptr)
}