diff options
| -rw-r--r-- | examples/01.minimal/Cargo.toml | 28 | ||||
| -rw-r--r-- | examples/01.minimal/build.rs | 0 | ||||
| -rw-r--r-- | examples/01.minimal/driver.rs | 16 | ||||
| -rw-r--r-- | examples/01.minimal/exports.def | 3 | ||||
| -rw-r--r-- | examples/02.unload/Cargo.toml | 28 | ||||
| -rw-r--r-- | examples/02.unload/build.rs | 0 | ||||
| -rw-r--r-- | examples/02.unload/driver.rs | 22 | ||||
| -rw-r--r-- | examples/02.unload/exports.def | 3 | ||||
| -rw-r--r-- | examples/03.urandom/Cargo.toml | 31 | ||||
| -rw-r--r-- | examples/03.urandom/build.cmd | 15 | ||||
| -rw-r--r-- | examples/03.urandom/build.rs | 0 | ||||
| -rw-r--r-- | examples/03.urandom/builddbg.cmd | 15 | ||||
| -rw-r--r-- | examples/03.urandom/buildrel.cmd | 15 | ||||
| -rw-r--r-- | examples/03.urandom/driver.rs | 171 | ||||
| -rw-r--r-- | examples/03.urandom/exports.def | 3 | ||||
| -rw-r--r-- | examples/README.md | 15 |
16 files changed, 365 insertions, 0 deletions
diff --git a/examples/01.minimal/Cargo.toml b/examples/01.minimal/Cargo.toml new file mode 100644 index 0000000..f1478aa --- /dev/null +++ b/examples/01.minimal/Cargo.toml @@ -0,0 +1,28 @@ +[package] +name = "rust.drv.examples.minimal" +description = "Minimal Windows kerneld driver sample." +version = "0.1.0" +authors = ["pravic <[email protected]>"] +readme = "../README.md" + +build = "build.rs" +links = "ntoskrnl" + +[lib] +path = "driver.rs" +name = "minimal" +crate-type = ["dylib"] + +test = false +bench = false + +[profile.release] +opt-level = 3 +debug = true +rpath = false +lto = true +debug-assertions = false + +[dependencies] +winapi-km = { path = "../../../km", version="*" } +core = { path = "../../../libcore", version = "*" } diff --git a/examples/01.minimal/build.rs b/examples/01.minimal/build.rs new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/examples/01.minimal/build.rs diff --git a/examples/01.minimal/driver.rs b/examples/01.minimal/driver.rs new file mode 100644 index 0000000..d446ff0 --- /dev/null +++ b/examples/01.minimal/driver.rs @@ -0,0 +1,16 @@ +#![crate_type = "dylib"] +#![no_std] +#![allow(bad_style)] + +#[macro_use] extern crate km; + +use core::mem; +use km::*; + +#[no_mangle] +pub extern "system" fn DriverEntry(_obj: *mut km::DRIVER_OBJECT, _path: *const km::string::UnicodeString) -> Status +{ + KdPrint!("[rs] hello, rust!\n"); + KdPrint!("[rs] we are DriverObject at 0x%p, sizeof %d\n", _obj, mem::size_of::<km::DRIVER_OBJECT>()); + return Status::unsuccessful; // return error to unload driver now +} diff --git a/examples/01.minimal/exports.def b/examples/01.minimal/exports.def new file mode 100644 index 0000000..15c494d --- /dev/null +++ b/examples/01.minimal/exports.def @@ -0,0 +1,3 @@ +EXPORTS + DriverEntry + diff --git a/examples/02.unload/Cargo.toml b/examples/02.unload/Cargo.toml new file mode 100644 index 0000000..69a1c49 --- /dev/null +++ b/examples/02.unload/Cargo.toml @@ -0,0 +1,28 @@ +[package] +name = "rust.drv.examples.unload" +description = "Simple Windows kernel driver which can be unloaded." +version = "0.1.0" +authors = ["pravic <[email protected]>"] +readme = "../README.md" + +build = "build.rs" +links = "ntoskrnl" + +[lib] +path = "driver.rs" +name = "unload" +crate-type = ["dylib"] + +test = false +bench = false + +[profile.release] +opt-level = 3 +debug = true +rpath = false +lto = true +debug-assertions = false + +[dependencies] +winapi-km = { path = "../../../km", version="*" } +core = { path = "../../../libcore", version = "*" } diff --git a/examples/02.unload/build.rs b/examples/02.unload/build.rs new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/examples/02.unload/build.rs diff --git a/examples/02.unload/driver.rs b/examples/02.unload/driver.rs new file mode 100644 index 0000000..6336045 --- /dev/null +++ b/examples/02.unload/driver.rs @@ -0,0 +1,22 @@ +#![crate_type = "dylib"] +#![no_std] +#![allow(bad_style)] + +#[macro_use] extern crate km; + +use core::mem; +use km::*; + +#[no_mangle] +pub extern "system" fn DriverEntry(driver: &mut km::DRIVER_OBJECT, _path: *const km::string::UnicodeString) -> Status { + + KdPrint!("[rs] hello, rust!\n"); + KdPrint!("[rs] we are DriverObject at 0x%p, sizeof %d\n", driver as *mut km::DRIVER_OBJECT , mem::size_of::<km::DRIVER_OBJECT>()); + + driver.DriverUnload = Some(DriverUnload); + return Status::success; +} + +extern "system" fn DriverUnload(_obj: &mut km::DRIVER_OBJECT) { + KdPrint!("[rs] unload.\n"); +} diff --git a/examples/02.unload/exports.def b/examples/02.unload/exports.def new file mode 100644 index 0000000..15c494d --- /dev/null +++ b/examples/02.unload/exports.def @@ -0,0 +1,3 @@ +EXPORTS + DriverEntry + diff --git a/examples/03.urandom/Cargo.toml b/examples/03.urandom/Cargo.toml new file mode 100644 index 0000000..a6628d1 --- /dev/null +++ b/examples/03.urandom/Cargo.toml @@ -0,0 +1,31 @@ +[package] +name = "rust.drv.examples.urandom" +description = "Windows kerneld driver sample which creates `\\\\.\\urandom` device." +version = "0.1.0" +authors = ["pravic <[email protected]>"] +readme = "../README.md" + +build = "build.rs" +links = "ntoskrnl" + +[lib] +path = "driver.rs" +name = "urandom" +crate-type = ["dylib"] + +test = false +bench = false + +[profile.release] +opt-level = 3 +debug = true +rpath = false +lto = true +debug-assertions = false + +[dependencies] +winapi-km = { path = "../../../km", version="*" } +core = { path = "../../../libcore", version = "*" } +collections = { path = "../../../libcollections" } +alloc = { path = "../../../liballoc" } +alloc_system= { path = "../../src/alloc"} diff --git a/examples/03.urandom/build.cmd b/examples/03.urandom/build.cmd new file mode 100644 index 0000000..8d86669 --- /dev/null +++ b/examples/03.urandom/build.cmd @@ -0,0 +1,15 @@ +call vcvars14 +@set KIND=release +@set NAME=urandom + +cargo build --%KIND% + +set LFLAGS=/NOLOGO /INCREMENTAL:NO /MANIFEST:NO /NODEFAULTLIB /SUBSYSTEM:NATIVE /DRIVER /RELEASE /DEBUG /NXCOMPAT /DYNAMICBASE /FIXED:No +set LLIBS=ntoskrnl.lib hal.lib +set RFLAGS=/OPT:REF /OPT:ICF +rem cpu-specific +set LPATH=/LIBPATH:"F:\DDK\7600\lib\win7\i386" +set LFLAGS=%LFLAGS% /MACHINE:X86 /entry:DriverEntry@8 +set TDIR=target\i786-pc-windows-msvc\%KIND% +link.exe %LFLAGS% %RFLAGS% %LPATH% %LLIBS% %TDIR%\%NAME%.lib /OUT:%TDIR%\%NAME%.sys +@pause diff --git a/examples/03.urandom/build.rs b/examples/03.urandom/build.rs new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/examples/03.urandom/build.rs diff --git a/examples/03.urandom/builddbg.cmd b/examples/03.urandom/builddbg.cmd new file mode 100644 index 0000000..031d63f --- /dev/null +++ b/examples/03.urandom/builddbg.cmd @@ -0,0 +1,15 @@ +call vcvars14 +@set KIND=debug +@set NAME=urandom + +cargo build + +set LFLAGS=/NOLOGO /INCREMENTAL:NO /MANIFEST:NO /NODEFAULTLIB /SUBSYSTEM:NATIVE /DRIVER /RELEASE /DEBUG /NXCOMPAT /DYNAMICBASE /FIXED:No +set LLIBS=ntoskrnl.lib hal.lib +set RFLAGS=/OPT:REF,ICF +rem cpu-specific +set LPATH=/LIBPATH:"F:\DDK\7600\lib\win7\i386" +set LFLAGS=%LFLAGS% /MACHINE:X86 /entry:DriverEntry@8 +set TDIR=target\i686-sys-windows-msvc\%KIND% +link.exe %LFLAGS% %RFLAGS% %LPATH% %LLIBS% %TDIR%\%NAME%.lib /OUT:%TDIR%\%NAME%.sys +@pause diff --git a/examples/03.urandom/buildrel.cmd b/examples/03.urandom/buildrel.cmd new file mode 100644 index 0000000..4c1e1fe --- /dev/null +++ b/examples/03.urandom/buildrel.cmd @@ -0,0 +1,15 @@ +call vcvars14 +@set KIND=release +@set NAME=urandom + +cargo build --%KIND% %* + +set LFLAGS=/NOLOGO /INCREMENTAL:NO /MANIFEST:NO /NODEFAULTLIB /SUBSYSTEM:NATIVE /DRIVER /RELEASE /DEBUG /NXCOMPAT /DYNAMICBASE /FIXED:No +set LLIBS=ntoskrnl.lib hal.lib +set RFLAGS=/OPT:REF /OPT:ICF +rem cpu-specific +set LPATH=/LIBPATH:"F:\DDK\7600\lib\win7\i386" +set LFLAGS=%LFLAGS% /MACHINE:X86 /entry:DriverEntry@8 +set TDIR=target\i686-sys-windows-msvc\%KIND% +link.exe %LFLAGS% %RFLAGS% %LPATH% %LLIBS% %TDIR%\lib%NAME%.lib /OUT:%TDIR%\%NAME%.sys +@pause diff --git a/examples/03.urandom/driver.rs b/examples/03.urandom/driver.rs new file mode 100644 index 0000000..7a98e48 --- /dev/null +++ b/examples/03.urandom/driver.rs @@ -0,0 +1,171 @@ +#![feature(collections)] + +#![no_std] +#![allow(bad_style)] + +#[macro_use] extern crate km; +#[macro_use] extern crate collections; + +use km::*; +use core::mem; +use core::ptr; + +// Helper for converting b"string" to UNICODE_STRING +fn a2u(s: &[u8]) -> UnicodeString { + let a = AnsiString::from(s); + let mut u = UnicodeString::default(); + unsafe { RtlAnsiStringToUnicodeString(&mut u, &a, true) }; + return u; +} + +// Our per-device settings payload +struct DEVICE_PARAMS +{ + pub name: UNICODE_STRING, + pub link: UNICODE_STRING, +} + +impl Drop for DEVICE_PARAMS +{ + fn drop(&mut self) { + unsafe { + RtlFreeUnicodeString(&mut self.name); + RtlFreeUnicodeString(&mut self.link); + } + } +} + + +#[no_mangle] +pub extern "system" fn DriverEntry(driver: &mut km::DRIVER_OBJECT, _path: &km::string::UnicodeString) -> NTSTATUS +{ + KdPrint!("[rs] hello, rust!\n"); + KdPrint!("[rs] we are DriverObject at 0x%p, sizeof 0x%X (expected size 0xA8 or 0x150)\n", + driver as *mut km::DRIVER_OBJECT, mem::size_of::<km::DRIVER_OBJECT>()); + + driver.DriverUnload = Some(DriverUnload); + + KdPrint!("[rs] make params\n"); + let params = DEVICE_PARAMS { name: a2u(b"\\Device\\RandomUDev\0"), link: a2u(b"\\??\\urandom\0"), }; + + // create device + KdPrint!("[rs] create device `%ws` (%d bytes len)\n", params.name.Buffer, params.name.Length as u32); + let mut device: *mut DEVICE_OBJECT = ptr::null_mut(); + check_unsafe!(IoCreateDevice(driver, mem::size_of::<DEVICE_PARAMS>() as u32, ¶ms.name, 34, 0, false, &mut device)); + + // store out custom params to DeviceExtension allocated memory + KdPrint!("[rs] store params at device\n"); + let device = unsafe { &mut *device }; + let pparams = device.DeviceExtension as *mut DEVICE_PARAMS; + let params = unsafe { + ptr::write(pparams, params); + &*pparams + }; + + // create symlink + KdPrint!("[rs] create symlink `%ws`\n", params.link.Buffer); + let st = unsafe { IoCreateSymbolicLink(¶ms.link, ¶ms.name) }; + if st.is_err() { + DriverUnload(driver); + return st; + } + + // setup I/O processing handlers + use km::irp::IRP_MJ; + driver.MajorFunction[IRP_MJ::CREATE as usize] = Some(DispatchCreateClose); + driver.MajorFunction[IRP_MJ::CLOSE as usize] = Some(DispatchCreateClose); + driver.MajorFunction[IRP_MJ::READ as usize] = Some(DispatchRead); + device.Flags |= DEVICE_FLAGS::DO_BUFFERED_IO as u32; + + KdPrint!("[rs] loaded.\n"); + return Status::success; +} + +extern "system" fn DriverUnload(driver: &mut km::DRIVER_OBJECT) +{ + KdPrint!("[rs] unload:\n"); + unsafe { + // for each created device (driver.DeviceObject->NextDevice linked list) + // delete symbolic link and delete device itself + let mut pdevice = driver.DeviceObject; + while !pdevice.is_null() { + KdPrint_u!("[rs] free device\n"); + let device = &mut *pdevice; + if !device.DeviceExtension.is_null() { + KdPrint_u!("[rs] drop params\n"); + let params = &mut *(device.DeviceExtension as *mut DEVICE_PARAMS); + IoDeleteSymbolicLink(¶ms.link); + drop(params); + } + KdPrint_u!("[rs] delete device\n"); + pdevice = device.NextDevice; + IoDeleteDevice(device); + } + } + KdPrint!("[rs] unloaded.\n"); +} + +extern "system" fn DispatchCreateClose(_device: &mut DEVICE_OBJECT, irp: &mut IRP) -> NTSTATUS { + KdPrint!("[rs] dispatch create/close \n"); + irp.IoStatus.Information = 0; + return irp.complete_request(Status::success); +} + +extern "system" fn DispatchRead(device: &mut DEVICE_OBJECT, irp: &mut IRP) -> NTSTATUS +{ + KdPrint!("[rs] dispatch read\n"); + if (device.Flags & DEVICE_FLAGS::DO_BUFFERED_IO as u32) == 0 { + KdPrint!("[rs] error: nonbuffered io!\n"); + return irp.complete_request(Status::unsuccessful); + } + + // process IRP request + let size = + { + let io = irp.get_current_stack_location(); + let args = io.ParametersRead(); + args.Length as usize + }; + KdPrint!("[rs] read size %d\n", size as i32); + + if size == 0 { + KdPrint!("[rs] error: empty buffer!\n"); + return irp.complete_request(Status::unsuccessful); + } + + KdPrint!("[rs] generate random\n"); + let buf = irp.SystemBuffer; // AssociatedIrp.SystemBuffer union. + let r = GenerateRandom(buf, size); + let st = if let Ok(size) = r { + irp.IoStatus.Information = size; + Status::success + } else { + r.err().unwrap() + }; + return irp.complete_request(st); +} + +// RtlRandom: Random number generator based on MacLaren and Marsaglia. +// RtlRandomEx is twice as fast and produces better random numbers +// since the period of the random numbers generated is comparatively higher. +fn GenerateRandom(buffer: PVOID, size: usize) -> Result<usize> { + let mut seed = km::time::QueryTickCount() as u32; + let data = buffer as *mut u32; + let dwords = size / 4; + let tail = size % 4; + KdPrint!("[rs] generate random for %d bytes as %d words and %d padding\n", size as u32, dwords as u32, tail as u32); + unsafe { + let mut i = 0; + while i < dwords { + let word = km::rtl::RtlRandomEx(&mut seed); + *data.offset(i as isize) = word; + i += 1; + } + if tail != 0 { + let word = km::rtl::RtlRandomEx(&mut seed); + km::crt::memcpy(data.offset(dwords as isize) as *mut u8, &word as *const u32 as *const u8, tail); + } + } + KdPrint!("[rs] generate complete\n"); + return Ok(size); +} diff --git a/examples/03.urandom/exports.def b/examples/03.urandom/exports.def new file mode 100644 index 0000000..15c494d --- /dev/null +++ b/examples/03.urandom/exports.def @@ -0,0 +1,3 @@ +EXPORTS + DriverEntry + diff --git a/examples/README.md b/examples/README.md new file mode 100644 index 0000000..7d30dee --- /dev/null +++ b/examples/README.md @@ -0,0 +1,15 @@ +## 01.minimal + +Minimal Windows kernel driver written in Rust. [DriverEntry](https://msdn.microsoft.com/en-us/library/windows/hardware/ff544113%28v=vs.85%29.aspx) just prints `hello` and quits immediately. + +## 02.unload + +Simple kernel driver which supports [unloading](https://msdn.microsoft.com/en-us/library/windows/hardware/ff564886%28v=vs.85%29.aspx). + +## 03.urandom + +[devrandom](https://github.com/pravic/ontl/tree/master/samples/devrandom) driver sample which has been ported to Rust. + +It creates `\\.\urandom` device, which can produce random data like `/dev/urandom`, but insecure. + +This sample shows how to create a [Device Object](https://msdn.microsoft.com/en-us/library/windows/hardware/ff548014%28v=vs.85%29.aspx), assotiate it with user-mode visible [name](https://msdn.microsoft.com/en-us/library/windows/hardware/ff556420%28v=vs.85%29.aspx) and process [I/O requests](https://msdn.microsoft.com/en-us/library/windows/hardware/ff544248%28v=vs.85%29.aspx) from user-mode applications. |