One binary setup

This commit is contained in:
nganhkhoa 2020-08-01 04:47:38 +07:00
parent 967684f140
commit e2eac767e0
9 changed files with 535 additions and 27 deletions

119
Cargo.lock generated
View File

@ -1,5 +1,13 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "ansi_term"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "anyhow"
version = "1.0.26"
@ -139,6 +147,20 @@ dependencies = [
"time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "clap"
version = "2.33.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
"atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
"bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
"vec_map 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "constant_time_eq"
version = "0.1.5"
@ -509,14 +531,17 @@ version = "0.1.0"
dependencies = [
"app_dirs 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"chrono 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)",
"clap 2.33.1 (registry+https://github.com/rust-lang/crates.io-index)",
"parse_int 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"pdb 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"pest 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
"pest_derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"prettytable-rs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"reqwest 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rust-embed 5.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rustyline 6.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.55 (registry+https://github.com/rust-lang/crates.io-index)",
"vergen 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"widestring 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -955,6 +980,35 @@ dependencies = [
"crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rust-embed"
version = "5.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"rust-embed-impl 5.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rust-embed-utils 5.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"walkdir 2.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rust-embed-impl"
version = "5.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"rust-embed-utils 5.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)",
"walkdir 2.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rust-embed-utils"
version = "5.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"walkdir 2.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rustc_version"
version = "0.2.3"
@ -986,6 +1040,14 @@ name = "ryu"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "same-file"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi-util 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "schannel"
version = "0.1.17"
@ -1112,6 +1174,11 @@ name = "sourcefile"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "strsim"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "syn"
version = "0.15.44"
@ -1155,6 +1222,14 @@ dependencies = [
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "textwrap"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "time"
version = "0.1.42"
@ -1292,6 +1367,20 @@ name = "vcpkg"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "vec_map"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "vergen"
version = "3.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"chrono 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "version_check"
version = "0.1.5"
@ -1307,6 +1396,16 @@ name = "void"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "walkdir"
version = "2.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"same-file 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi-util 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "want"
version = "0.3.0"
@ -1447,6 +1546,14 @@ name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "winapi-util"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
@ -1475,6 +1582,7 @@ version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[metadata]
"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
"checksum anyhow 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)" = "7825f6833612eb2414095684fcf6c635becf3ce97fe48cf6421321e93bfbd53c"
"checksum app_dirs 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e73a24bad9bd6a94d6395382a6c69fe071708ae4409f763c5475e14ee896313d"
"checksum arrayref 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544"
@ -1495,6 +1603,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum cc 1.0.50 (registry+https://github.com/rust-lang/crates.io-index)" = "95e28fa049fda1c330bcf9d723be7663a899c4679724b34c81e9f5a326aab8cd"
"checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
"checksum chrono 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "31850b4a4d6bae316f7a09e691c944c28299298837edc0a03f755618c23cbc01"
"checksum clap 2.33.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bdfa80d47f954d53a35a64987ca1422f495b8d6483c0fe9f7117b36c2a792129"
"checksum constant_time_eq 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc"
"checksum core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "25b9e03f145fd4f2bf705e07b900cd41fc636598fe5dc452fd0db1441c3f496d"
"checksum core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e7ca8a5221364ef15ce201e8ed2f609fc312682a8f4e0e3d4aa5879764e0fa3b"
@ -1587,9 +1696,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e"
"checksum reqwest 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c0e798e19e258bf6c30a304622e3e9ac820e483b06a1857a026e1f109b113fe4"
"checksum rust-argon2 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2bc8af4bda8e1ff4932523b94d3dd20ee30a87232323eda55903ffd71d2fb017"
"checksum rust-embed 5.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "213acf1bc5a6dfcd70b62db1e9a7d06325c0e73439c312fcb8599d456d9686ee"
"checksum rust-embed-impl 5.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7903c2cf599db8f310b392332f38367ca4acc84420fa1aee3536299f433c10d5"
"checksum rust-embed-utils 5.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "97655158074ccb2d2cfb1ccb4c956ef0f4054e43a2c1e71146d4991e6961e105"
"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
"checksum rustyline 6.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3358c21cbbc1a751892528db4e1de4b7a2b6a73f001e215aaba97d712cfa9777"
"checksum ryu 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bfa8506c1de11c9c4e4c38863ccbe02a305c8188e85a05a784c9e11e1c3910c8"
"checksum same-file 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
"checksum schannel 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "507a9e6e8ffe0a4e0ebb9a10293e62fdf7657c06f1b8bb07a8fcf697d2abf295"
"checksum scopeguard 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
"checksum scroll 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2f84d114ef17fd144153d608fba7c446b0145d038985e7a8cc5d08bb0ce20383"
@ -1606,10 +1719,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8"
"checksum smallvec 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5c2fb2ec9bcd216a5b0d0ccf31ab17b5ed1d627960edff65bbe95d3ce221cefc"
"checksum sourcefile 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4bf77cb82ba8453b42b6ae1d692e4cdc92f9a47beaf89a847c8be83f4e328ad3"
"checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
"checksum syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)" = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5"
"checksum syn 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)" = "af6f3550d8dff9ef7dc34d384ac6f107e5d31c8f57d9f28e0081503f547ac8f5"
"checksum tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9"
"checksum term 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "edd106a334b7657c10b7c540a0106114feadeb4dc314513e97df481d5d966f42"
"checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
"checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f"
"checksum tokio 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8fdd17989496f49cdc57978c96f0c9fe5e4a58a8bddc6813c449a4624f6a030b"
"checksum tokio-tls 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7bde02a3a5291395f59b06ec6945a3077602fac2b07eeeaf0dee2122f3619828"
@ -1629,9 +1744,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum utf8parse 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "936e4b492acfd135421d8dca4b1aa80a7bfc26e702ef3af710e0752684df5372"
"checksum uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)" = "90dbc611eb48397705a6b0f6e917da23ae517e4d127123d2cf7674206627d32a"
"checksum vcpkg 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3fc439f2794e98976c88a2a2dafce96b930fe8010b0a256b3c2199a773933168"
"checksum vec_map 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
"checksum vergen 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4ce50d8996df1f85af15f2cd8d33daae6e479575123ef4314a51a70a230739cb"
"checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd"
"checksum version_check 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "078775d0255232fb988e6fccf26ddc9d1ac274299aaedcedce21c6f72cc533ce"
"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
"checksum walkdir 2.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "777182bc735b6424e1a57516d35ed72cb8019d85c8c9bf536dccb3445c1a2f7d"
"checksum want 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0"
"checksum wasi 0.9.0+wasi-snapshot-preview1 (registry+https://github.com/rust-lang/crates.io-index)" = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
"checksum wasm-bindgen 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)" = "5205e9afdf42282b192e2310a5b463a6d1c1d774e30dc3c791ac37ab42d2616c"
@ -1648,6 +1766,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6"
"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
"checksum winapi-util 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
"checksum winreg 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b2986deb581c4fe11b621998a5e53361efe6b48a151178d0cd9eeffa4dc6acc9"
"checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e"

View File

@ -25,3 +25,8 @@ pest = "2.1.3"
pest_derive = "2.1.0"
# others
prettytable-rs = "^0.8"
rust-embed="5.6.0"
clap="2.33.1"
[build-dependencies]
vergen="3.1.0"

8
build.rs Normal file
View File

@ -0,0 +1,8 @@
extern crate vergen;
use vergen::{generate_cargo_keys, ConstantsFlags};
fn main() {
let flags = ConstantsFlags::all();
generate_cargo_keys(flags).expect("Unable to generate the cargo keys!");
}

143
src/bin/lpus.rs Normal file
View File

@ -0,0 +1,143 @@
use serde_json::json;
use std::error::Error;
use std::fs;
use std::io::Write;
extern crate clap;
extern crate prettytable;
use app_dirs::{app_dir, AppDataType};
use clap::{App, Arg, SubCommand};
use rust_embed::RustEmbed;
#[derive(RustEmbed)]
#[folder = "resource"]
struct Asset;
use lpus::{
commands::{driverscan, modscan, psxview, ssdt, unloadedmodules},
driver_state::DriverState,
APP_INFO,
};
fn extract_driver() {
let driver_bytes = Asset::get("lpus.sys").unwrap();
let mut driver_location =
app_dir(AppDataType::UserData, &APP_INFO, &format!("driver")).unwrap();
driver_location.push("lpus.sys");
println!("driver location: {:?}", driver_location);
if let Ok(mut f) = fs::File::create(driver_location) {
f.write_all(&driver_bytes).unwrap();
}
}
fn main() -> Result<(), Box<dyn Error>> {
let version = format!(
"{}-{} commit on {}",
env!("VERGEN_SEMVER"),
env!("VERGEN_SHA_SHORT"),
env!("VERGEN_COMMIT_DATE")
);
let matches = App::new("LPUS")
.version(&*version)
.author("Khoa Nguyen Anh <mail.nganhkhoa@gmail.com>")
.about("Live memory fornesics on Windows")
.arg(
Arg::with_name("load")
.short("l")
.help("Load the driver and exit"),
)
.arg(
Arg::with_name("unload")
.short("u")
.help("Unload the driver and exit"),
)
.subcommand(
SubCommand::with_name("repl").about("Run the Interactive REPL (in development)"),
)
.subcommand(SubCommand::with_name("pdb").about("Inspect the PDB file"))
.subcommand(
SubCommand::with_name("hide_notepad")
.about("Compare processes found from multiple commands"),
)
.subcommand(
SubCommand::with_name("psxview")
.about("Compare processes found from multiple commands"),
)
.subcommand(
SubCommand::with_name("unloadedmodules")
.about("Compare processes found from multiple commands"),
)
.subcommand(
SubCommand::with_name("modscan")
.about("Compare processes found from multiple commands"),
)
.subcommand(
SubCommand::with_name("driverscan")
.about("Compare processes found from multiple commands"),
)
.subcommand(
SubCommand::with_name("ssdt")
.about("Dump the SSDT table")
.arg(
Arg::with_name("hook")
.short("h")
.help("print only hooked function"),
),
)
.get_matches();
extract_driver();
let mut driver = DriverState::new();
if !driver.is_supported() {
return Err(format!(
"Windows version {:?} is not supported",
driver.windows_ffi.short_version
)
.into());
}
if matches.is_present("load") {
println!("NtLoadDriver() -> 0x{:x}", driver.startup());
return Ok(());
}
if matches.is_present("unload") {
println!("NtUnloadDriver() -> 0x{:x}", driver.shutdown());
return Ok(());
}
driver.connect();
if let Some(_c) = matches.subcommand_matches("hide_notepad") {
driver.hide_notepad();
return Ok(());
}
if let Some(c) = matches.subcommand_matches("ssdt") {
ssdt(&driver, c.is_present("hook"));
return Ok(());
}
if let Some(_c) = matches.subcommand_matches("psxview") {
psxview(&driver);
return Ok(());
}
if let Some(_c) = matches.subcommand_matches("unloadedmodules") {
unloadedmodules(&driver);
return Ok(());
}
if let Some(_c) = matches.subcommand_matches("driverscan") {
driverscan(&driver);
return Ok(());
}
if let Some(_c) = matches.subcommand_matches("modscan") {
modscan(&driver);
return Ok(());
}
Ok(())
}

190
src/commands.rs Normal file
View File

@ -0,0 +1,190 @@
use serde_json::Value;
use std::collections::HashSet;
use std::error::Error;
use prettytable::{cell, row, Table};
use parse_int::parse;
use crate::{
driver_state::DriverState, scan_driver, scan_eprocess, scan_ethread, scan_kernel_module,
ssdt_table, traverse_activehead, traverse_handletable, traverse_kiprocesslist,
traverse_loadedmodulelist, traverse_unloadeddrivers,
};
pub fn ssdt(driver: &DriverState, only_hooked: bool) {
let loaded = traverse_loadedmodulelist(&driver).unwrap_or(Vec::new());
let ssdt = ssdt_table(&driver).unwrap_or(Vec::new());
let ntosbase = driver.get_kernel_base();
for (idx, func) in ssdt.iter().enumerate() {
let owner = loaded.iter().find_map(|r| {
let base = r["dllbase"]
.as_str()
.and_then(|b| parse::<u64>(b).ok())
.unwrap_or(0);
let size = r["size"]
.as_str()
.and_then(|s| parse::<u64>(s).ok())
.unwrap_or(0);
if *func > base && *func < base + size {
let module = r["BaseName"].as_str().unwrap();
Some(module)
} else {
None
}
});
if owner == Some("ntoskrnl.exe") {
if !only_hooked {
let offset = func - ntosbase.address();
let funcname: String = {
driver
.pdb_store
.symbols
.iter()
.find_map(|(name, o)| {
if o.clone() == offset {
Some(name.clone())
} else {
None
}
})
.unwrap_or("(??)".to_string())
};
println!("SSDT [{}]\t0x{:x}", idx, func);
println!("\towned by nt!{}", funcname);
}
} else if let Some(owner_) = owner {
println!("SSDT [{}]\t0x{:x}", idx, func);
println!("\\thooked by {}", owner_);
} else {
println!("SSDT [{}]\t0x{:x}", idx, func);
println!("\tmissing owner");
}
}
}
pub fn psxview(driver: &DriverState) {
fn process_in_list(addr: &str, list: &Vec<Value>) -> bool {
for r in list.iter() {
if r["address"].as_str().unwrap() == addr {
return true;
}
}
false
}
fn get_from_list(addr: &str, list: &Vec<Value>) -> Option<Value> {
for r in list.iter() {
if r["address"].as_str().unwrap() == addr {
return Some(r.clone());
}
}
None
}
fn process_in_list_thread(addr: &str, list: &Vec<Value>) -> bool {
for r in list.iter() {
if r["eprocess"].as_str().unwrap() == addr {
return true;
}
}
false
}
let process_scan = scan_eprocess(&driver).unwrap_or(Vec::new());
let thread_scan = scan_ethread(&driver).unwrap_or(Vec::new());
let activehead = traverse_activehead(&driver).unwrap_or(Vec::new());
let kiprocesslist = traverse_kiprocesslist(&driver).unwrap_or(Vec::new());
let handletable = traverse_handletable(&driver).unwrap_or(Vec::new());
let mut unique_process = HashSet::new();
for list in [&process_scan, &activehead, &kiprocesslist, &handletable].iter() {
for r in list.iter() {
let addr = r["address"].as_str().unwrap();
unique_process.insert(addr);
}
}
let mut table = Table::new();
table.add_row(row![
"Address",
"Name",
"pid",
"ppid",
"PoolTagScan",
"ActiveProcessHead",
"KiProcessListHead",
"HandleTableList",
"ThreadScan"
]);
for p in &unique_process {
let addr = p.to_string();
let v = {
if let Some(vv) = get_from_list(&addr, &activehead) {
vv
} else {
get_from_list(&addr, &process_scan).unwrap_or_default()
}
};
table.add_row(row![
&addr,
v["name"].as_str().unwrap_or("(??)"),
v["pid"].as_i64().unwrap_or(-1),
v["ppid"].as_i64().unwrap_or(-1),
process_in_list(&addr, &process_scan),
process_in_list(&addr, &activehead),
process_in_list(&addr, &kiprocesslist),
process_in_list(&addr, &handletable),
process_in_list_thread(&addr, &thread_scan)
]);
}
table.printstd();
}
pub fn modscan(driver: &DriverState) {
let dd = scan_kernel_module(&driver).unwrap_or(Vec::new());
let mut table = Table::new();
table.add_row(row!["Address", "Base name", "Base", "Size", "File"]);
for d in &dd {
table.add_row(row![
d["address"].as_str().unwrap_or("(??)"),
d["BaseName"].as_str().unwrap_or("(??)"),
d["dllbase"].as_str().unwrap_or("(??)"),
d["size"].as_str().unwrap_or("(??)"),
d["FullName"].as_str().unwrap_or("(??)"),
]);
}
table.printstd();
}
pub fn driverscan(driver: &DriverState) {
let dd = scan_driver(&driver).unwrap_or(Vec::new());
let mut table = Table::new();
table.add_row(row!["Address", "Device", "Service key", "Start", "Size"]);
for d in &dd {
table.add_row(row![
d["address"].as_str().unwrap_or("(??)"),
d["device"].as_str().unwrap_or("(??)"),
d["servicekey"].as_str().unwrap_or("(??)"),
d["start"].as_str().unwrap_or("(??)"),
d["size"].as_str().unwrap_or("(??)"),
]);
}
table.printstd();
}
pub fn unloadedmodules(driver: &DriverState) {
let modules = traverse_unloadeddrivers(&driver).unwrap_or(Vec::new());
let mut table = Table::new();
table.add_row(row!["Address", "Driver", "Start", "End", "Time"]);
for m in &modules {
table.add_row(row![
m["address"].as_str().unwrap_or("(??)"),
m["name"].as_str().unwrap_or("(??)"),
m["start_addr"].as_str().unwrap_or("(??)"),
m["end_addr"].as_str().unwrap_or("(??)"),
m["time_rfc2822"].as_str().unwrap_or("(??)"),
]);
}
table.printstd();
}

View File

@ -14,8 +14,7 @@ use winapi::um::winioctl::{
use crate::address::Address;
use crate::ioctl_protocol::{
DerefAddr, InputData, /* OutputData, */ Nothing, OffsetData,
ScanPoolData, /* HideProcess, */
DerefAddr, HideProcess, InputData, /* OutputData, */ Nothing, OffsetData, ScanPoolData,
};
use crate::pdb_store::{parse_pdb, PdbStore};
use crate::windows::{WindowsFFI, WindowsVersion};
@ -120,10 +119,34 @@ impl DriverState {
self.windows_ffi.unload_driver()
}
pub fn connect(&mut self) {
self.windows_ffi.file_connect();
}
pub fn is_supported(&self) -> bool {
self.windows_ffi.short_version.is_supported()
}
pub fn hide_notepad(&self) {
let s = String::from("notepad.exe");
let s_bytes = s.as_bytes();
let mut name = [0u8; 15];
for i in 0..s.len() {
name[i] = s_bytes[i];
}
let mut input = InputData {
hide_process: HideProcess {
name,
size: s.len() as u64,
},
};
self.windows_ffi.device_io(
DriverAction::HideProcess.get_code(),
&mut input,
&mut Nothing,
);
}
pub fn use_old_tag(&self) -> bool {
// use old tag to scan, for Window < 8
if self.windows_ffi.short_version < WindowsVersion::Windows8 {

View File

@ -2,12 +2,14 @@ extern crate app_dirs;
extern crate chrono;
pub mod address;
pub mod commands;
pub mod driver_state;
pub mod ioctl_protocol;
pub mod object;
pub mod pdb_store;
pub mod windows;
use app_dirs::AppInfo;
use chrono::{DateTime, Local, TimeZone};
use serde_json::{json, Value};
use std::error::Error;
@ -18,6 +20,11 @@ use object::*;
type BoxResult<T> = Result<T, Box<dyn Error>>;
pub const APP_INFO: AppInfo = AppInfo {
name: "lpus",
author: "nganhkhoa",
};
pub fn to_epoch(filetime: u64) -> DateTime<Local> {
// return seconds from epoch
let windows_epoch_diff = 11_644_473_600_000 * 10_000;
@ -369,9 +376,7 @@ pub fn scan_driver(driver: &DriverState) -> BoxResult<Vec<Value>> {
while try_ptr <= valid_end {
// No documentation on type constrain
let size: u16 = driver.decompose(&try_ptr, "_DRIVER_OBJECT.Size")?;
if (size as u64) == dob_size
/* && ftype == 5u16 */
{
if (size as u64) == dob_size {
break;
}
try_ptr += 0x4; // search exhaustively
@ -538,7 +543,7 @@ pub fn traverse_unloadeddrivers(driver: &DriverState) -> BoxResult<Vec<Value>> {
let unload_array = driver.deref_addr_new::<u64>(unload_array_ptr.address());
if unload_array == 0 {
return Err("The unload driver list is null".into());
return Err("The unload driver list pointer is null".into());
}
// by reversing MmLocateUnloadedDriver
@ -553,6 +558,7 @@ pub fn traverse_unloadeddrivers(driver: &DriverState) -> BoxResult<Vec<Value>> {
let start_addr: u64 = driver.decompose(&driver_addr, "_UNLOADED_DRIVERS.StartAddress")?;
let end_addr: u64 = driver.decompose(&driver_addr, "_UNLOADED_DRIVERS.EndAddress")?;
let current_time: u64 = driver.decompose(&driver_addr, "_UNLOADED_DRIVERS.CurrentTime")?;
let time = to_epoch(current_time);
result.push(json!({
"address": format!("0x{:x}", driver_addr.address()),
@ -560,7 +566,8 @@ pub fn traverse_unloadeddrivers(driver: &DriverState) -> BoxResult<Vec<Value>> {
"name": name,
"start_addr": format!("0x{:x}", start_addr),
"end_addr": format!("0x{:x}", end_addr),
"current_time": driver.windows_ffi.to_epoch(current_time)
"time_unix": time.timestamp(),
"time_rfc2822": time.to_rfc2822()
}));
}

View File

@ -5,18 +5,14 @@ use std::io;
use std::io::Read;
use std::path::PathBuf;
use app_dirs::{app_dir, AppDataType, AppInfo};
use app_dirs::{app_dir, AppDataType};
use pdb::{
ClassType, FallibleIterator, ModifierType, Rva, SymbolData, TypeData, TypeFinder, TypeIndex,
PDB,
};
use crate::address::Address;
const APP_INFO: AppInfo = AppInfo {
name: "lpus",
author: "nganhkhoa",
};
use crate::APP_INFO;
const KERNEL_PDB_NAME: &str = "ntkrnlmp.pdb";
const NTOSKRNL_PATH: &str = "C:\\Windows\\System32\\ntoskrnl.exe";

View File

@ -2,8 +2,12 @@ use std::ffi::{c_void, CString};
use std::mem::{size_of_val, transmute};
use std::ptr::null_mut;
use std::time::{SystemTime, UNIX_EPOCH};
use app_dirs::{app_dir, AppDataType};
use widestring::U16CString;
use crate::APP_INFO;
use winapi::shared::minwindef::{DWORD, HKEY, HMODULE};
use winapi::shared::ntdef::*;
use winapi::um::winnt::{
@ -80,8 +84,17 @@ impl WindowsFFI {
let str_rtl_init_unicode_str = CString::new("RtlInitUnicodeString").unwrap();
let str_rtl_get_version = CString::new("RtlGetVersion").unwrap();
let str_se_load_driver_privilege = CString::new("SeLoadDriverPrivilege").unwrap();
let str_driver_path = CString::new("\\SystemRoot\\System32\\DRIVERS\\lpus.sys").unwrap();
let str_driver_path = {
let mut driver_location =
app_dir(AppDataType::UserData, &APP_INFO, &format!("driver")).unwrap();
driver_location.push("lpus.sys");
if driver_location.is_file() {
let p = driver_location.to_str().unwrap();
CString::new(format!("\\??\\{}", p)).unwrap()
} else {
CString::new("\\SystemRoot\\System32\\DRIVERS\\lpus.sys").unwrap()
}
};
let str_registry_path = CString::new("System\\CurrentControlSet\\Services\\lpus").unwrap();
let str_type = CString::new("Type").unwrap();
let str_error_control = CString::new("ErrorControl").unwrap();
@ -217,21 +230,11 @@ impl WindowsFFI {
}
}
pub fn driver_loaded(self) -> bool {
pub fn driver_loaded(&self) -> bool {
self.driver_handle != INVALID_HANDLE_VALUE
}
pub fn load_driver(&mut self) -> NTSTATUS {
// TODO: Move this to new()
// If we move this function to new(), self.driver_handle will be init, and thus no mut here
let str_driver_reg = U16CString::from_str(STR_DRIVER_REGISTRY_PATH).unwrap();
let mut str_driver_reg_unicode = UNICODE_STRING::default();
(self.rtl_init_unicode_str)(
&mut str_driver_reg_unicode,
str_driver_reg.as_ptr() as *const u16,
);
let status = (self.nt_load_driver)(&mut str_driver_reg_unicode);
pub fn file_connect(&mut self) {
let filename = CString::new("\\\\.\\poolscanner").unwrap();
let driver_file_handle: HANDLE = unsafe {
CreateFileA(
@ -250,6 +253,20 @@ impl WindowsFFI {
} else {
self.driver_handle = driver_file_handle;
}
}
pub fn load_driver(&mut self) -> NTSTATUS {
// TODO: Move this to new()
// If we move this function to new(), self.driver_handle will be init, and thus no mut here
let str_driver_reg = U16CString::from_str(STR_DRIVER_REGISTRY_PATH).unwrap();
let mut str_driver_reg_unicode = UNICODE_STRING::default();
(self.rtl_init_unicode_str)(
&mut str_driver_reg_unicode,
str_driver_reg.as_ptr() as *const u16,
);
let status = (self.nt_load_driver)(&mut str_driver_reg_unicode);
self.file_connect();
status
}