|
1 | 1 | extern crate alloc; |
2 | 2 |
|
3 | | -use crate::{gdt, nt, user}; |
| 3 | +use crate::{gdt, nt, println, user}; |
| 4 | +use core::sync::atomic::{AtomicUsize, Ordering}; |
4 | 5 | use x86_64::instructions::segmentation::Segment; |
5 | 6 | use x86_64::registers::model_specific::{ |
6 | 7 | Efer, EferFlags, GsBase, KernelGsBase, LStar, SFMask, Star, |
@@ -32,6 +33,8 @@ static mut SYSCALL_CPU_LOCALS: [SyscallCpuLocal; MAX_CPUS] = [const { |
32 | 33 |
|
33 | 34 | static mut SYSCALL_STACKS: [SyscallStack; MAX_CPUS] = |
34 | 35 | [const { SyscallStack([0; SYSCALL_STACK_SIZE]) }; MAX_CPUS]; |
| 36 | +static UNKNOWN_SYSCALL_LOG_COUNT: AtomicUsize = AtomicUsize::new(0); |
| 37 | +static FAILED_SYSCALL_LOG_COUNT: AtomicUsize = AtomicUsize::new(0); |
35 | 38 |
|
36 | 39 | #[repr(C)] |
37 | 40 | pub struct SyscallFrame { |
@@ -168,23 +171,154 @@ extern "sysv64" fn syscall_dispatch(frame: *mut SyscallFrame) -> usize { |
168 | 171 | } |
169 | 172 | let frame = unsafe { &*frame }; |
170 | 173 | let result = match frame.nr { |
| 174 | + // Windows x64 native syscall compatibility for real ntdll stubs. |
| 175 | + 4 => user::wait_for_single_object(frame.r10, frame.rdx != 0, frame.r8 as *const i64) as usize, |
| 176 | + 6 => user::read_file( |
| 177 | + frame.r10, |
| 178 | + stack_arg(frame, 0) as *mut nt::IoStatusBlock, |
| 179 | + stack_arg(frame, 1) as *mut u8, |
| 180 | + stack_arg(frame, 2), |
| 181 | + ) as usize, |
| 182 | + 7 => user::device_io_control_file( |
| 183 | + frame.r10, |
| 184 | + frame.rdx, |
| 185 | + frame.r8 as *mut (), |
| 186 | + frame.r9 as *mut (), |
| 187 | + stack_arg(frame, 0) as *mut nt::IoStatusBlock, |
| 188 | + stack_arg(frame, 1) as u32, |
| 189 | + stack_arg(frame, 2) as *const u8, |
| 190 | + stack_arg(frame, 3) as u32, |
| 191 | + stack_arg(frame, 4) as *mut u8, |
| 192 | + stack_arg(frame, 5) as u32, |
| 193 | + ) as usize, |
| 194 | + 8 => user::write_file( |
| 195 | + frame.r10, |
| 196 | + stack_arg(frame, 0) as *mut nt::IoStatusBlock, |
| 197 | + stack_arg(frame, 1) as *const u8, |
| 198 | + stack_arg(frame, 2), |
| 199 | + ) as usize, |
| 200 | + 14 => user::set_event(frame.r10, frame.rdx as *mut i32) as usize, |
| 201 | + 15 => user::close_handle(frame.r10) as usize, |
| 202 | + 17 => user::query_information_file( |
| 203 | + frame.r10, |
| 204 | + frame.rdx as *mut nt::IoStatusBlock, |
| 205 | + frame.r8 as *mut u8, |
| 206 | + frame.r9 as u32, |
| 207 | + stack_arg(frame, 0) as u32, |
| 208 | + ) as usize, |
| 209 | + 24 if frame.rdx != 0 && frame.r9 != 0 => user::allocate_virtual_memory( |
| 210 | + frame.r10, |
| 211 | + frame.rdx as *mut usize, |
| 212 | + frame.r9 as *mut usize, |
| 213 | + stack_arg(frame, 1) as u32, |
| 214 | + ) as usize, |
| 215 | + 25 => user::query_information_process( |
| 216 | + frame.r10, |
| 217 | + frame.rdx as u32, |
| 218 | + frame.r8 as *mut u8, |
| 219 | + frame.r9 as u32, |
| 220 | + stack_arg(frame, 0) as *mut u32, |
| 221 | + ) as usize, |
| 222 | + 30 => user::free_virtual_memory( |
| 223 | + frame.r10, |
| 224 | + frame.rdx as *mut usize, |
| 225 | + frame.r8 as *mut usize, |
| 226 | + ) as usize, |
| 227 | + 35 => user::query_virtual_memory( |
| 228 | + frame.r10, |
| 229 | + frame.rdx, |
| 230 | + frame.r8 as u32, |
| 231 | + frame.r9 as *mut u8, |
| 232 | + stack_arg(frame, 0), |
| 233 | + stack_arg(frame, 1) as *mut usize, |
| 234 | + ) as usize, |
| 235 | + 39 => user::query_information_file( |
| 236 | + frame.r10, |
| 237 | + frame.rdx as *mut nt::IoStatusBlock, |
| 238 | + frame.r8 as *mut u8, |
| 239 | + frame.r9 as u32, |
| 240 | + stack_arg(frame, 0) as u32, |
| 241 | + ) as usize, |
| 242 | + 40 => user::map_view_of_section( |
| 243 | + frame.r10, |
| 244 | + frame.rdx, |
| 245 | + frame.r8 as *mut usize, |
| 246 | + stack_arg(frame, 3) as *mut usize, |
| 247 | + stack_arg(frame, 6) as u32, |
| 248 | + ) as usize, |
| 249 | + 42 => user::unmap_view_of_section(frame.r10, frame.rdx) as usize, |
| 250 | + // Windows native syscall number for NtTerminateProcess on recent x64 builds. |
| 251 | + 44 => user::terminate_process(frame.r10, frame.rdx as i32) as usize, |
| 252 | + 51 => user::create_file( |
| 253 | + frame.r10 as *mut usize, |
| 254 | + frame.rdx as u32, |
| 255 | + frame.r8 as *const nt::ObjectAttributes, |
| 256 | + frame.r9 as *mut nt::IoStatusBlock, |
| 257 | + ) as usize, |
| 258 | + 52 => user::delay_execution(frame.r10 != 0, frame.rdx as *const i64) as usize, |
171 | 259 | // Windows native syscall number for NtQuerySystemInformation on recent x64 builds. |
172 | 260 | 54 => user::query_system_information( |
173 | 261 | frame.r10 as u32, |
174 | 262 | frame.rdx as *mut u8, |
175 | 263 | frame.r8 as u32, |
176 | 264 | frame.r9 as *mut u32, |
177 | 265 | ) as usize, |
178 | | - // Windows native syscall number for NtAllocateVirtualMemory on recent x64 builds. |
179 | | - // Args: (ProcessHandle, BaseAddress*, ZeroBits, RegionSize*, AllocationType, Protect) |
180 | | - 24 if frame.rdx != 0 && frame.r9 != 0 => user::allocate_virtual_memory( |
| 266 | + 55 => user::open_section( |
| 267 | + frame.r10 as *mut usize, |
| 268 | + frame.rdx as u32, |
| 269 | + frame.r8 as *const nt::ObjectAttributes, |
| 270 | + ) as usize, |
| 271 | + 57 => user::device_io_control_file( |
181 | 272 | frame.r10, |
182 | | - frame.rdx as *mut usize, |
183 | | - frame.r9 as *mut usize, |
| 273 | + frame.rdx, |
| 274 | + frame.r8 as *mut (), |
| 275 | + frame.r9 as *mut (), |
| 276 | + stack_arg(frame, 0) as *mut nt::IoStatusBlock, |
184 | 277 | stack_arg(frame, 1) as u32, |
| 278 | + stack_arg(frame, 2) as *const u8, |
| 279 | + stack_arg(frame, 3) as u32, |
| 280 | + stack_arg(frame, 4) as *mut u8, |
| 281 | + stack_arg(frame, 5) as u32, |
185 | 282 | ) as usize, |
186 | | - // Windows native syscall number for NtTerminateProcess on recent x64 builds. |
187 | | - 44 => user::terminate_process(frame.r10, frame.rdx as i32) as usize, |
| 283 | + 62 => user::clear_event(frame.r10) as usize, |
| 284 | + 70 => user::yield_execution() as usize, |
| 285 | + 72 => user::create_event( |
| 286 | + frame.r10 as *mut usize, |
| 287 | + frame.r9 as u32, |
| 288 | + stack_arg(frame, 0) != 0, |
| 289 | + ) as usize, |
| 290 | + 73 => user::query_information_file( |
| 291 | + frame.r10, |
| 292 | + frame.rdx as *mut nt::IoStatusBlock, |
| 293 | + frame.r8 as *mut u8, |
| 294 | + frame.r9 as u32, |
| 295 | + stack_arg(frame, 0) as u32, |
| 296 | + ) as usize, |
| 297 | + 74 => user::create_section( |
| 298 | + frame.r10 as *mut usize, |
| 299 | + frame.rdx as u32, |
| 300 | + frame.r8 as *const nt::ObjectAttributes, |
| 301 | + frame.r9 as *const i64, |
| 302 | + stack_arg(frame, 0) as u32, |
| 303 | + stack_arg(frame, 1) as u32, |
| 304 | + stack_arg(frame, 2), |
| 305 | + ) as usize, |
| 306 | + 80 => user::protect_virtual_memory( |
| 307 | + frame.r10, |
| 308 | + frame.rdx as *mut usize, |
| 309 | + frame.r8 as *mut usize, |
| 310 | + frame.r9 as u32, |
| 311 | + stack_arg(frame, 0) as *mut u32, |
| 312 | + ) as usize, |
| 313 | + 83 => user::terminate_thread(frame.r10, frame.rdx as i32) as usize, |
| 314 | + 85 => user::create_file( |
| 315 | + frame.r10 as *mut usize, |
| 316 | + frame.rdx as u32, |
| 317 | + frame.r8 as *const nt::ObjectAttributes, |
| 318 | + frame.r9 as *mut nt::IoStatusBlock, |
| 319 | + ) as usize, |
| 320 | + 91 => user::query_system_time(frame.r10 as *mut i64) as usize, |
| 321 | + 228 => user::display_string(frame.r10 as *const nt::UnicodeString) as usize, |
188 | 322 | nt::SYSCALL_NT_CLOSE => user::close_handle(frame.a0) as usize, |
189 | 323 | nt::SYSCALL_NT_QUERY_INFORMATION_PROCESS => user::query_information_process( |
190 | 324 | frame.a0, |
@@ -323,7 +457,34 @@ extern "sysv64" fn syscall_dispatch(frame: *mut SyscallFrame) -> usize { |
323 | 457 | stack_arg(frame, 3) as usize, |
324 | 458 | stack_arg(frame, 4) as *const (), |
325 | 459 | ) as usize, |
326 | | - _ => nt::STATUS_NOT_IMPLEMENTED as usize, |
| 460 | + _ => { |
| 461 | + let seen = UNKNOWN_SYSCALL_LOG_COUNT.fetch_add(1, Ordering::Relaxed); |
| 462 | + if seen < 128 { |
| 463 | + println!( |
| 464 | + "NT KERNEL: unknown syscall nr={} rcx={:#x} r10={:#x} rdx={:#x} r8={:#x} r9={:#x}", |
| 465 | + frame.nr, |
| 466 | + frame.rcx, |
| 467 | + frame.r10, |
| 468 | + frame.rdx, |
| 469 | + frame.r8, |
| 470 | + frame.r9 |
| 471 | + ); |
| 472 | + } |
| 473 | + nt::STATUS_NOT_IMPLEMENTED as usize |
| 474 | + } |
327 | 475 | }; |
| 476 | + if result != nt::STATUS_SUCCESS as usize |
| 477 | + && result != nt::STATUS_TIMEOUT as usize |
| 478 | + && result != nt::STATUS_END_OF_FILE as usize |
| 479 | + && result != nt::STATUS_INVALID_DEVICE_REQUEST as usize |
| 480 | + { |
| 481 | + let seen = FAILED_SYSCALL_LOG_COUNT.fetch_add(1, Ordering::Relaxed); |
| 482 | + if seen < 256 { |
| 483 | + println!( |
| 484 | + "NT KERNEL: syscall failure nr={} status={:#x} rcx={:#x} r10={:#x}", |
| 485 | + frame.nr, result as u32, frame.rcx, frame.r10 |
| 486 | + ); |
| 487 | + } |
| 488 | + } |
328 | 489 | result |
329 | 490 | } |
0 commit comments