aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--examples/01.minimal/Cargo.toml28
-rw-r--r--examples/01.minimal/build.rs0
-rw-r--r--examples/01.minimal/driver.rs16
-rw-r--r--examples/01.minimal/exports.def3
-rw-r--r--examples/02.unload/Cargo.toml28
-rw-r--r--examples/02.unload/build.rs0
-rw-r--r--examples/02.unload/driver.rs22
-rw-r--r--examples/02.unload/exports.def3
-rw-r--r--examples/03.urandom/Cargo.toml31
-rw-r--r--examples/03.urandom/build.cmd15
-rw-r--r--examples/03.urandom/build.rs0
-rw-r--r--examples/03.urandom/builddbg.cmd15
-rw-r--r--examples/03.urandom/buildrel.cmd15
-rw-r--r--examples/03.urandom/driver.rs171
-rw-r--r--examples/03.urandom/exports.def3
-rw-r--r--examples/README.md15
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, &params.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(&params.link, &params.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(&params.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.