use crate::windows::constants::*;
use crate::emu::Emu;
use super::sync;
fn alpc_create_handle(emu: &mut Emu, nr: u64, name: &str) {
let handle_out = emu.regs().rcx;
log_orange!(emu, "syscall 0x{:x}: {} out: 0x{:x}", nr, name, handle_out);
if handle_out != 0 && emu.maps.is_mapped(handle_out) {
let h = sync::next_handle();
let _ = emu.maps.write_qword(handle_out, h);
}
emu.regs_mut().rax = STATUS_SUCCESS;
}
fn alpc_query_info(emu: &mut Emu, nr: u64, name: &str) {
let info_buf = emu.regs().r9;
let rsp = emu.regs().rsp;
let length = emu.maps.read_qword(rsp + 0x28).unwrap_or(0);
log_orange!(emu, "syscall 0x{:x}: {} buf: 0x{:x} len: 0x{:x}", nr, name, info_buf, length);
if info_buf != 0 && emu.maps.is_mapped(info_buf) {
let sz = length.min(0x1000) as usize;
for i in 0..sz {
let _ = emu.maps.write_byte(info_buf + i as u64, 0);
}
}
emu.regs_mut().rax = STATUS_SUCCESS;
}
fn alpc_noop(emu: &mut Emu, nr: u64, name: &str) {
log_orange!(emu, "syscall 0x{:x}: {} (stub)", nr, name);
emu.regs_mut().rax = STATUS_SUCCESS;
}
pub fn nt_alpc_connect_port(emu: &mut Emu) {
let handle_out = emu.regs().rcx;
let rsp = emu.regs().rsp;
let conn_msg_ptr = emu.maps.read_qword(rsp + 0x38).unwrap_or(0);
log_orange!(
emu,
"syscall 0x{:x}: NtAlpcConnectPort out: 0x{:x}, conn_msg: 0x{:x}",
WIN64_NTALPCCONNECTPORT,
handle_out,
conn_msg_ptr,
);
if handle_out != 0 && emu.maps.is_mapped(handle_out) {
let h = sync::next_handle();
let _ = emu.maps.write_qword(handle_out, h);
}
if conn_msg_ptr != 0 && emu.maps.is_mapped(conn_msg_ptr) {
for off in 0..0x200u64 {
let _ = emu.maps.write_byte(conn_msg_ptr + off, 0);
}
}
emu.regs_mut().rax = STATUS_SUCCESS;
}
pub fn nt_alpc_connect_port_ex(emu: &mut Emu) {
alpc_create_handle(emu, WIN64_NTALPCCONNECTPORTEX, "NtAlpcConnectPortEx");
}
pub fn nt_alpc_create_port(emu: &mut Emu) {
alpc_create_handle(emu, WIN64_NTALPCCREATEPORT, "NtAlpcCreatePort");
}
pub fn nt_alpc_create_port_section(emu: &mut Emu) {
alpc_create_handle(emu, WIN64_NTALPCCREATEPORTSECTION, "NtAlpcCreatePortSection");
}
pub fn nt_alpc_create_resource_reserve(emu: &mut Emu) {
alpc_create_handle(emu, WIN64_NTALPCCREATERESOURCERESERVE, "NtAlpcCreateResourceReserve");
}
pub fn nt_alpc_create_section_view(emu: &mut Emu) {
alpc_create_handle(emu, WIN64_NTALPCCREATESECTIONVIEW, "NtAlpcCreateSectionView");
}
pub fn nt_alpc_create_security_context(emu: &mut Emu) {
alpc_create_handle(emu, WIN64_NTALPCCREATESECURITYCONTEXT, "NtAlpcCreateSecurityContext");
}
pub fn nt_alpc_query_information(emu: &mut Emu) {
alpc_query_info(emu, WIN64_NTALPCQUERYINFORMATION, "NtAlpcQueryInformation");
}
pub fn nt_alpc_query_information_message(emu: &mut Emu) {
let port = emu.regs().rcx;
let class = emu.regs().r8;
let info = emu.regs().r9;
let rsp = emu.regs().rsp;
let length = emu.maps.read_qword(rsp + 0x28).unwrap_or(0);
let ret_len= emu.maps.read_qword(rsp + 0x30).unwrap_or(0);
log_orange!(
emu,
"syscall 0x{:x}: NtAlpcQueryInformationMessage port: 0x{:x}, class: 0x{:x}, buf: 0x{:x}, len: 0x{:x}",
WIN64_NTALPCQUERYINFORMATIONMESSAGE,
port,
class,
info,
length,
);
if info != 0 && emu.maps.is_mapped(info) {
let sz = length.min(0x1000) as usize;
for i in 0..sz {
let _ = emu.maps.write_byte(info + i as u64, 0);
}
}
if ret_len != 0 && emu.maps.is_mapped(ret_len) {
let _ = emu.maps.write_qword(ret_len, length.min(0x1000));
}
emu.regs_mut().rax = STATUS_SUCCESS;
}
pub fn nt_alpc_cancel_message(emu: &mut Emu) {
alpc_noop(emu, WIN64_NTALPCCANCELMESSAGE, "NtAlpcCancelMessage");
}
pub fn nt_alpc_delete_port_section(emu: &mut Emu) {
alpc_noop(emu, WIN64_NTALPCDELETEPORTSECTION, "NtAlpcDeletePortSection");
}
pub fn nt_alpc_delete_resource_reserve(emu: &mut Emu) {
alpc_noop(emu, WIN64_NTALPCDELETERESOURCERESERVE, "NtAlpcDeleteResourceReserve");
}
pub fn nt_alpc_delete_section_view(emu: &mut Emu) {
alpc_noop(emu, WIN64_NTALPCDELETESECTIONVIEW, "NtAlpcDeleteSectionView");
}
pub fn nt_alpc_delete_security_context(emu: &mut Emu) {
alpc_noop(emu, WIN64_NTALPCDELETESECURITYCONTEXT, "NtAlpcDeleteSecurityContext");
}
pub fn nt_alpc_disconnect_port(emu: &mut Emu) {
alpc_noop(emu, WIN64_NTALPCDISCONNECTPORT, "NtAlpcDisconnectPort");
}
pub fn nt_alpc_impersonate_client_container_of_port(emu: &mut Emu) {
alpc_noop(emu, WIN64_NTALPCIMPERSONATECLIENTCONTAINEROFPORT, "NtAlpcImpersonateClientContainerOfPort");
}
pub fn nt_alpc_impersonate_client_of_port(emu: &mut Emu) {
alpc_noop(emu, WIN64_NTALPCIMPERSONATECLIENTOFPORT, "NtAlpcImpersonateClientOfPort");
}
pub fn nt_alpc_open_sender_process(emu: &mut Emu) {
alpc_create_handle(emu, WIN64_NTALPCOPENSENDERPROCESS, "NtAlpcOpenSenderProcess");
}
pub fn nt_alpc_open_sender_thread(emu: &mut Emu) {
alpc_create_handle(emu, WIN64_NTALPCOPENSENDERTHREAD, "NtAlpcOpenSenderThread");
}
pub fn nt_alpc_revoke_security_context(emu: &mut Emu) {
alpc_noop(emu, WIN64_NTALPCREVOKESECURITYCONTEXT, "NtAlpcRevokeSecurityContext");
}
const LPC_REPLY: u16 = 2;
const PORT_MESSAGE_SIZE: u64 = 0x28;
pub fn nt_alpc_send_wait_receive_port(emu: &mut Emu) {
let port = emu.regs().rcx;
let send_msg_ptr = emu.regs().r8;
let rsp = emu.regs().rsp;
let recv_msg_ptr = emu.maps.read_qword(rsp + 0x28).unwrap_or(0);
let send_data_len = if send_msg_ptr != 0 && emu.maps.is_mapped(send_msg_ptr) {
emu.maps.read_word(send_msg_ptr).unwrap_or(0)
} else {
0
};
log_orange!(
emu,
"syscall 0x{:x}: NtAlpcSendWaitReceivePort port: 0x{:x}, send: 0x{:x}, recv_buf: 0x{:x}",
WIN64_NTALPCSENDWAITRECEIVEPORT,
port,
send_msg_ptr,
recv_msg_ptr,
);
if recv_msg_ptr != 0 && emu.maps.is_mapped(recv_msg_ptr) {
let data_len = send_data_len.min(0x1e0) as u64;
for off in 0..(PORT_MESSAGE_SIZE + data_len) {
let _ = emu.maps.write_byte(recv_msg_ptr + off, 0);
}
let _ = emu.maps.write_word(recv_msg_ptr + 0x00, send_data_len);
let _ = emu.maps.write_word(recv_msg_ptr + 0x02, PORT_MESSAGE_SIZE as u16 + send_data_len);
let _ = emu.maps.write_word(recv_msg_ptr + 0x04, LPC_REPLY);
}
emu.regs_mut().rax = STATUS_SUCCESS;
}
pub fn nt_alpc_set_information(emu: &mut Emu) {
alpc_noop(emu, WIN64_NTALPCSETINFORMATION, "NtAlpcSetInformation");
}