feat: 添加dump进程功能
This commit is contained in:
parent
8835ca5f26
commit
253cfcd399
151
src-tauri/Cargo.lock
generated
151
src-tauri/Cargo.lock
generated
@ -520,6 +520,25 @@ dependencies = [
|
|||||||
"crossbeam-utils",
|
"crossbeam-utils",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-deque"
|
||||||
|
version = "0.8.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d"
|
||||||
|
dependencies = [
|
||||||
|
"crossbeam-epoch",
|
||||||
|
"crossbeam-utils",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-epoch"
|
||||||
|
version = "0.9.18"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
|
||||||
|
dependencies = [
|
||||||
|
"crossbeam-utils",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crossbeam-utils"
|
name = "crossbeam-utils"
|
||||||
version = "0.8.20"
|
version = "0.8.20"
|
||||||
@ -753,6 +772,12 @@ version = "1.0.17"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125"
|
checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "either"
|
||||||
|
version = "1.13.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "embed-resource"
|
name = "embed-resource"
|
||||||
version = "2.5.1"
|
version = "2.5.1"
|
||||||
@ -864,11 +889,13 @@ dependencies = [
|
|||||||
"memmap2",
|
"memmap2",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
"sysinfo",
|
||||||
"tauri",
|
"tauri",
|
||||||
"tauri-build",
|
"tauri-build",
|
||||||
"tauri-plugin-dialog",
|
"tauri-plugin-dialog",
|
||||||
"tauri-plugin-shell",
|
"tauri-plugin-shell",
|
||||||
"thiserror 2.0.4",
|
"thiserror 2.0.4",
|
||||||
|
"windows 0.58.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -2047,6 +2074,15 @@ version = "0.1.14"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb"
|
checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ntapi"
|
||||||
|
version = "0.4.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e8a3895c6391c39d7fe7ebc444a87eb2991b2a0bc718fdabd071eec617fc68e4"
|
||||||
|
dependencies = [
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-conv"
|
name = "num-conv"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
@ -2809,6 +2845,26 @@ version = "0.6.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539"
|
checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rayon"
|
||||||
|
version = "1.10.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa"
|
||||||
|
dependencies = [
|
||||||
|
"either",
|
||||||
|
"rayon-core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rayon-core"
|
||||||
|
version = "1.12.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2"
|
||||||
|
dependencies = [
|
||||||
|
"crossbeam-deque",
|
||||||
|
"crossbeam-utils",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "redox_syscall"
|
name = "redox_syscall"
|
||||||
version = "0.5.7"
|
version = "0.5.7"
|
||||||
@ -3395,6 +3451,20 @@ dependencies = [
|
|||||||
"syn 2.0.90",
|
"syn 2.0.90",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sysinfo"
|
||||||
|
version = "0.33.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "948512566b1895f93b1592c7574baeb2de842f224f2aab158799ecadb8ebbb46"
|
||||||
|
dependencies = [
|
||||||
|
"core-foundation-sys",
|
||||||
|
"libc",
|
||||||
|
"memchr",
|
||||||
|
"ntapi",
|
||||||
|
"rayon",
|
||||||
|
"windows 0.57.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "system-deps"
|
name = "system-deps"
|
||||||
version = "6.2.2"
|
version = "6.2.2"
|
||||||
@ -3441,7 +3511,7 @@ dependencies = [
|
|||||||
"tao-macros",
|
"tao-macros",
|
||||||
"unicode-segmentation",
|
"unicode-segmentation",
|
||||||
"url",
|
"url",
|
||||||
"windows",
|
"windows 0.58.0",
|
||||||
"windows-core 0.58.0",
|
"windows-core 0.58.0",
|
||||||
"windows-version",
|
"windows-version",
|
||||||
"x11-dl",
|
"x11-dl",
|
||||||
@ -3511,7 +3581,7 @@ dependencies = [
|
|||||||
"webkit2gtk",
|
"webkit2gtk",
|
||||||
"webview2-com",
|
"webview2-com",
|
||||||
"window-vibrancy",
|
"window-vibrancy",
|
||||||
"windows",
|
"windows 0.58.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -3672,7 +3742,7 @@ dependencies = [
|
|||||||
"tauri-utils",
|
"tauri-utils",
|
||||||
"thiserror 2.0.4",
|
"thiserror 2.0.4",
|
||||||
"url",
|
"url",
|
||||||
"windows",
|
"windows 0.58.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -3697,7 +3767,7 @@ dependencies = [
|
|||||||
"url",
|
"url",
|
||||||
"webkit2gtk",
|
"webkit2gtk",
|
||||||
"webview2-com",
|
"webview2-com",
|
||||||
"windows",
|
"windows 0.58.0",
|
||||||
"wry",
|
"wry",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -4416,10 +4486,10 @@ checksum = "6f61ff3d9d0ee4efcb461b14eb3acfda2702d10dc329f339303fc3e57215ae2c"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"webview2-com-macros",
|
"webview2-com-macros",
|
||||||
"webview2-com-sys",
|
"webview2-com-sys",
|
||||||
"windows",
|
"windows 0.58.0",
|
||||||
"windows-core 0.58.0",
|
"windows-core 0.58.0",
|
||||||
"windows-implement",
|
"windows-implement 0.58.0",
|
||||||
"windows-interface",
|
"windows-interface 0.58.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -4440,7 +4510,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "a3a3e2eeb58f82361c93f9777014668eb3d07e7d174ee4c819575a9208011886"
|
checksum = "a3a3e2eeb58f82361c93f9777014668eb3d07e7d174ee4c819575a9208011886"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"thiserror 1.0.69",
|
"thiserror 1.0.69",
|
||||||
"windows",
|
"windows 0.58.0",
|
||||||
"windows-core 0.58.0",
|
"windows-core 0.58.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -4489,6 +4559,16 @@ dependencies = [
|
|||||||
"windows-version",
|
"windows-version",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows"
|
||||||
|
version = "0.57.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "12342cb4d8e3b046f3d80effd474a7a02447231330ef77d71daa6fbc40681143"
|
||||||
|
dependencies = [
|
||||||
|
"windows-core 0.57.0",
|
||||||
|
"windows-targets 0.52.6",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows"
|
name = "windows"
|
||||||
version = "0.58.0"
|
version = "0.58.0"
|
||||||
@ -4508,19 +4588,42 @@ dependencies = [
|
|||||||
"windows-targets 0.52.6",
|
"windows-targets 0.52.6",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-core"
|
||||||
|
version = "0.57.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d2ed2439a290666cd67ecce2b0ffaad89c2a56b976b736e6ece670297897832d"
|
||||||
|
dependencies = [
|
||||||
|
"windows-implement 0.57.0",
|
||||||
|
"windows-interface 0.57.0",
|
||||||
|
"windows-result 0.1.2",
|
||||||
|
"windows-targets 0.52.6",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows-core"
|
name = "windows-core"
|
||||||
version = "0.58.0"
|
version = "0.58.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6ba6d44ec8c2591c134257ce647b7ea6b20335bf6379a27dac5f1641fcf59f99"
|
checksum = "6ba6d44ec8c2591c134257ce647b7ea6b20335bf6379a27dac5f1641fcf59f99"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"windows-implement",
|
"windows-implement 0.58.0",
|
||||||
"windows-interface",
|
"windows-interface 0.58.0",
|
||||||
"windows-result",
|
"windows-result 0.2.0",
|
||||||
"windows-strings",
|
"windows-strings",
|
||||||
"windows-targets 0.52.6",
|
"windows-targets 0.52.6",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-implement"
|
||||||
|
version = "0.57.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9107ddc059d5b6fbfbffdfa7a7fe3e22a226def0b2608f72e9d552763d3e1ad7"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.90",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows-implement"
|
name = "windows-implement"
|
||||||
version = "0.58.0"
|
version = "0.58.0"
|
||||||
@ -4532,6 +4635,17 @@ dependencies = [
|
|||||||
"syn 2.0.90",
|
"syn 2.0.90",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-interface"
|
||||||
|
version = "0.57.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "29bee4b38ea3cde66011baa44dba677c432a78593e202392d1e9070cf2a7fca7"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.90",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows-interface"
|
name = "windows-interface"
|
||||||
version = "0.58.0"
|
version = "0.58.0"
|
||||||
@ -4549,11 +4663,20 @@ version = "0.2.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0"
|
checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"windows-result",
|
"windows-result 0.2.0",
|
||||||
"windows-strings",
|
"windows-strings",
|
||||||
"windows-targets 0.52.6",
|
"windows-targets 0.52.6",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-result"
|
||||||
|
version = "0.1.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5e383302e8ec8515204254685643de10811af0ed97ea37210dc26fb0032647f8"
|
||||||
|
dependencies = [
|
||||||
|
"windows-targets 0.52.6",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows-result"
|
name = "windows-result"
|
||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
@ -4569,7 +4692,7 @@ version = "0.1.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10"
|
checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"windows-result",
|
"windows-result 0.2.0",
|
||||||
"windows-targets 0.52.6",
|
"windows-targets 0.52.6",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -4873,7 +4996,7 @@ dependencies = [
|
|||||||
"webkit2gtk",
|
"webkit2gtk",
|
||||||
"webkit2gtk-sys",
|
"webkit2gtk-sys",
|
||||||
"webview2-com",
|
"webview2-com",
|
||||||
"windows",
|
"windows 0.58.0",
|
||||||
"windows-core 0.58.0",
|
"windows-core 0.58.0",
|
||||||
"windows-version",
|
"windows-version",
|
||||||
"x11-dl",
|
"x11-dl",
|
||||||
|
@ -18,11 +18,23 @@ name = "test_tauri_lib"
|
|||||||
tauri-build = {version = "2", features = [] }
|
tauri-build = {version = "2", features = [] }
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bitflags = {version= "2.6.0", features = ["serde"] }
|
bitflags = {version = "2.6.0", features = ["serde"] }
|
||||||
memmap2 = "0.9.5"
|
memmap2 = "0.9.5"
|
||||||
serde = {version = "1", features = ["derive"] }
|
serde = {version = "1", features = ["derive"] }
|
||||||
serde_json = "1"
|
serde_json = "1"
|
||||||
|
sysinfo = "0.33.0"
|
||||||
tauri = {version = "2", features = [] }
|
tauri = {version = "2", features = [] }
|
||||||
tauri-plugin-dialog = "2"
|
tauri-plugin-dialog = "2"
|
||||||
tauri-plugin-shell = "2"
|
tauri-plugin-shell = "2"
|
||||||
thiserror = "2.0.4"
|
thiserror = "2.0.4"
|
||||||
|
|
||||||
|
[dependencies.windows]
|
||||||
|
version = "0.58.0"
|
||||||
|
features = [
|
||||||
|
"Data_Xml_Dom",
|
||||||
|
"Win32_Foundation",
|
||||||
|
"Win32_Security",
|
||||||
|
"Win32_System_Threading",
|
||||||
|
"Win32_UI_WindowsAndMessaging",
|
||||||
|
"Win32_System_ProcessStatus"
|
||||||
|
]
|
||||||
|
@ -38,6 +38,11 @@ pub enum AppError {
|
|||||||
/// 节名过长
|
/// 节名过长
|
||||||
#[error("节名过长!")]
|
#[error("节名过长!")]
|
||||||
SectionNameTooLong,
|
SectionNameTooLong,
|
||||||
|
|
||||||
|
#[error("打开进程失败!: {0}")]
|
||||||
|
OpenProcessError(String),
|
||||||
|
#[error("查询进程路径失败!: {0}")]
|
||||||
|
QueryFullProcessImageNameWError(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl serde::Serialize for AppError {
|
impl serde::Serialize for AppError {
|
||||||
|
@ -128,7 +128,6 @@ impl AppState {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub fn get_import_tables(&self) -> Result<Vec<ImportModuleTable>, AppError> {
|
pub fn get_import_tables(&self) -> Result<Vec<ImportModuleTable>, AppError> {
|
||||||
let mmap = self.get_mmap_ref()?;
|
let mmap = self.get_mmap_ref()?;
|
||||||
let is_64_bit = self.is_64_bit.unwrap();
|
let is_64_bit = self.is_64_bit.unwrap();
|
||||||
@ -204,6 +203,9 @@ impl AppState {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
let mut import_function_table = ImportFunctionTable::default();
|
let mut import_function_table = ImportFunctionTable::default();
|
||||||
|
|
||||||
|
if is_named == true {
|
||||||
|
// TODO: 仅当序号/名称标志位字段为 0(按名称导入)时,才使用此字段。
|
||||||
let hint_name_table_rva = import_lookup_table as u32 & 0x7FFFFFFF;
|
let hint_name_table_rva = import_lookup_table as u32 & 0x7FFFFFFF;
|
||||||
let hint_name_table_foa = mmap.rva_to_foa(hint_name_table_rva)?;
|
let hint_name_table_foa = mmap.rva_to_foa(hint_name_table_rva)?;
|
||||||
// 1. 读hint 两个字节
|
// 1. 读hint 两个字节
|
||||||
@ -213,22 +215,17 @@ impl AppState {
|
|||||||
};
|
};
|
||||||
import_function_table.function_hint = funtion_hint;
|
import_function_table.function_hint = funtion_hint;
|
||||||
import_function_table.function_address = hint_name_table_rva;
|
import_function_table.function_address = hint_name_table_rva;
|
||||||
match is_named {
|
|
||||||
true => {
|
|
||||||
// 命名函数
|
|
||||||
let function_name = unsafe {
|
let function_name = unsafe {
|
||||||
let ptr =
|
let ptr = mmap[hint_name_table_foa as usize + 2..].as_ptr() as *const i8;
|
||||||
mmap[hint_name_table_foa as usize + 2..].as_ptr() as *const i8;
|
|
||||||
CStr::from_ptr(ptr).to_str()?.to_string()
|
CStr::from_ptr(ptr).to_str()?.to_string()
|
||||||
};
|
};
|
||||||
import_function_table.function_name = function_name;
|
import_function_table.function_name = function_name;
|
||||||
functions.push(import_function_table);
|
} else {
|
||||||
}
|
let function_ordianl = import_lookup_table as u32 & ImportLookupTable32::IMPORT_BY_ORDINAL_MASK.bits();
|
||||||
false => {
|
import_function_table.function_hint = function_ordianl as u16;
|
||||||
import_function_table.function_type = ImportFunctionTableItem::Ordinal;
|
import_function_table.function_type = ImportFunctionTableItem::Ordinal;
|
||||||
|
}
|
||||||
functions.push(import_function_table);
|
functions.push(import_function_table);
|
||||||
}
|
|
||||||
}
|
|
||||||
// 下一个
|
// 下一个
|
||||||
base_offset += if is_64_bit { 8 } else { 4 };
|
base_offset += if is_64_bit { 8 } else { 4 };
|
||||||
}
|
}
|
||||||
@ -266,5 +263,5 @@ pub struct ImportFunctionTable {
|
|||||||
pub function_name: String, // 函数名称
|
pub function_name: String, // 函数名称
|
||||||
pub function_address: u32, // 函数地址 IAT
|
pub function_address: u32, // 函数地址 IAT
|
||||||
pub function_hint: u16, // 函数提示
|
pub function_hint: u16, // 函数提示
|
||||||
pub function_type: ImportFunctionTableItem
|
pub function_type: ImportFunctionTableItem,
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ use crate::pe_parse::pe::{
|
|||||||
MutablePE
|
MutablePE
|
||||||
};
|
};
|
||||||
pub mod file;
|
pub mod file;
|
||||||
|
pub mod win_proc;
|
||||||
|
|
||||||
// 为文件映射实现PE结构
|
// 为文件映射实现PE结构
|
||||||
impl ReadOnlyPE for Mmap {}
|
impl ReadOnlyPE for Mmap {}
|
||||||
|
213
src-tauri/src/services/win_proc.rs
Normal file
213
src-tauri/src/services/win_proc.rs
Normal file
@ -0,0 +1,213 @@
|
|||||||
|
use std::{alloc::{alloc, Layout}, io::{Seek, Write}};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
app_error::AppError,
|
||||||
|
pe_parse::{header::ImageDosHeader, pe::ReadOnlyPE},
|
||||||
|
};
|
||||||
|
use memmap2::Mmap;
|
||||||
|
use sysinfo::{self, System};
|
||||||
|
use windows::{
|
||||||
|
core::PWSTR,
|
||||||
|
Win32::{
|
||||||
|
Foundation::{CloseHandle, HMODULE},
|
||||||
|
System::{
|
||||||
|
Diagnostics::Debug::ReadProcessMemory,
|
||||||
|
ProcessStatus::EnumProcessModules,
|
||||||
|
Threading::{
|
||||||
|
OpenProcess, QueryFullProcessImageNameW, PROCESS_ACCESS_RIGHTS, PROCESS_ALL_ACCESS,
|
||||||
|
PROCESS_NAME_WIN32,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
/// 遍历进程并返回进程名\PID
|
||||||
|
pub fn get_process_list() -> Vec<(String, u32)> {
|
||||||
|
let mut sys = System::new_all();
|
||||||
|
sys.refresh_all();
|
||||||
|
let mut process_list = Vec::new();
|
||||||
|
for (pid, process) in sys.processes() {
|
||||||
|
let pid = pid.as_u32();
|
||||||
|
process_list.push((process.name().to_str().unwrap().to_string(), pid));
|
||||||
|
}
|
||||||
|
process_list
|
||||||
|
}
|
||||||
|
pub fn dump_process(pid: u32, save_file_path: &str) -> Result<(), AppError> {
|
||||||
|
#[warn(unused_assignments)]
|
||||||
|
let mut file_path = String::new();
|
||||||
|
// 1. 打开进程
|
||||||
|
|
||||||
|
let mut image_base = 0; // 模块基址
|
||||||
|
let h_process = unsafe {
|
||||||
|
OpenProcess(PROCESS_ACCESS_RIGHTS(PROCESS_ALL_ACCESS.0), false, pid)
|
||||||
|
.map_err(|e| AppError::OpenProcessError(e.to_string()))?
|
||||||
|
};
|
||||||
|
// 2. 获取进程对应的文件路径
|
||||||
|
let mut buffer = [0u16; 1024];
|
||||||
|
let pwstr = PWSTR(buffer.as_mut_ptr());
|
||||||
|
let mut size = buffer.len() as u32;
|
||||||
|
unsafe {
|
||||||
|
let result = QueryFullProcessImageNameW(h_process, PROCESS_NAME_WIN32, pwstr, &mut size);
|
||||||
|
if result.is_err() {
|
||||||
|
return Err(AppError::QueryFullProcessImageNameWError(
|
||||||
|
result.unwrap_err().to_string(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
unsafe {
|
||||||
|
file_path = pwstr.to_string().unwrap();
|
||||||
|
println!("进程路径: {:?}", file_path);
|
||||||
|
}
|
||||||
|
// 创建新文件
|
||||||
|
let mut save_file = std::fs::OpenOptions::new()
|
||||||
|
.write(true)
|
||||||
|
.create(true)
|
||||||
|
.open(save_file_path)
|
||||||
|
.map_err(|e| AppError::Io(e))?;
|
||||||
|
|
||||||
|
// 3. 读取进程的文件,读取它的PE头
|
||||||
|
// 3.1 映射文件
|
||||||
|
let file = std::fs::OpenOptions::new()
|
||||||
|
.read(true)
|
||||||
|
.open(file_path)
|
||||||
|
.map_err(|e| AppError::Io(e))?;
|
||||||
|
let mmap = unsafe { Mmap::map(&file).map_err(|e| AppError::Io(e)) }?;
|
||||||
|
// 3.2 读取PE头
|
||||||
|
{
|
||||||
|
// 3.2.1 读取DOS头
|
||||||
|
let dos_header = mmap.get_dos_header()?;
|
||||||
|
let write_size = std::mem::size_of::<ImageDosHeader>() as u64;
|
||||||
|
save_file.write_all(&mmap[..write_size as usize])?;
|
||||||
|
// 3.2.2 读取PE头
|
||||||
|
let nt_header = mmap.get_nt_header()?;
|
||||||
|
let nt_header_size = match nt_header {
|
||||||
|
crate::pe_parse::header::ImageNTHeader::NTHeader32(_) => {
|
||||||
|
std::mem::size_of::<crate::pe_parse::header::ImageNTHeader32>() as u64
|
||||||
|
}
|
||||||
|
crate::pe_parse::header::ImageNTHeader::NTHeader64(_) => {
|
||||||
|
std::mem::size_of::<crate::pe_parse::header::ImageNTHeader64>() as u64
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let nt_header_offset = dos_header.e_lfanew;
|
||||||
|
// 移动文件指针
|
||||||
|
save_file.seek(std::io::SeekFrom::Start(nt_header_offset.0 as u64))?;
|
||||||
|
// 写入PE头
|
||||||
|
save_file.write_all(
|
||||||
|
&mmap[nt_header_offset.0 as usize
|
||||||
|
..(nt_header_offset.0 as usize + nt_header_size as usize) as usize],
|
||||||
|
)?;
|
||||||
|
// 写入nt_header_offset.0 - sizeof(dos_header)的数据
|
||||||
|
// 移动文件指针到dos_header之后
|
||||||
|
save_file.seek(std::io::SeekFrom::Start(write_size))?;
|
||||||
|
save_file.write_all(&mmap[write_size as usize..nt_header_offset.0 as usize])?;
|
||||||
|
// 移动文件指针到最后
|
||||||
|
save_file.seek(std::io::SeekFrom::Start(
|
||||||
|
nt_header_offset.0 as u64 + nt_header_size,
|
||||||
|
))?;
|
||||||
|
// 数据目录
|
||||||
|
let data_directory_offset = nt_header_offset.0 as usize + nt_header_size as usize;
|
||||||
|
save_file.write_all(&mmap[data_directory_offset..data_directory_offset + 16 * 17])?;
|
||||||
|
// 节区头
|
||||||
|
let sections_num = mmap.get_section_headers()?.len();
|
||||||
|
let section_header_offset = mmap.get_section_headers_offset()?;
|
||||||
|
let section_header_size = std::mem::size_of::<crate::pe_parse::header::ImageSectionHeader>()
|
||||||
|
as u64
|
||||||
|
* sections_num as u64;
|
||||||
|
save_file.seek(std::io::SeekFrom::Start(section_header_offset as u64))?;
|
||||||
|
save_file.write_all(
|
||||||
|
&mmap[section_header_offset as usize
|
||||||
|
..(section_header_offset as usize + section_header_size as usize) as usize],
|
||||||
|
)?;
|
||||||
|
save_file.flush()?;
|
||||||
|
}
|
||||||
|
// 获取模块基址
|
||||||
|
{
|
||||||
|
let mut h_module = HMODULE::default();
|
||||||
|
let mut cb_needed = 0;
|
||||||
|
unsafe {
|
||||||
|
EnumProcessModules(
|
||||||
|
h_process,
|
||||||
|
&mut h_module,
|
||||||
|
std::mem::size_of::<HMODULE>() as u32,
|
||||||
|
&mut cb_needed,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
// 获取模块基址
|
||||||
|
image_base = h_module.0 as u64;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 5. 遍历节表头,从进程中读取节的内容,写入文件
|
||||||
|
{
|
||||||
|
let sections = mmap.get_section_headers()?;
|
||||||
|
for section in sections.iter() {
|
||||||
|
let section_va = section.virtual_address as u64;
|
||||||
|
let section_size = section.size_of_raw_data as u64;
|
||||||
|
let section_size_align = mmap.align_size_with_section_alignment(section_size as u32)?;
|
||||||
|
let section_offset = image_base + section_va;
|
||||||
|
let section_foa = section.pointer_to_raw_data as u64;
|
||||||
|
|
||||||
|
let data_buf = unsafe {
|
||||||
|
let layout = Layout::array::<u8>(section_size_align as usize).unwrap();
|
||||||
|
alloc(layout)
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut read_size = 0;
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
ReadProcessMemory(
|
||||||
|
h_process,
|
||||||
|
section_offset as *const _,
|
||||||
|
data_buf as *mut _,
|
||||||
|
section_size_align as usize,
|
||||||
|
Some(&mut read_size),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
println!(
|
||||||
|
"读取节: VA: {:#x}, Size: {:#x}, FOA: {:#x}",
|
||||||
|
section_va, section_size, section_foa
|
||||||
|
);
|
||||||
|
println!(
|
||||||
|
"读取节: Size: {:#x}, ReadSize: {:#x}",
|
||||||
|
section_size_align, read_size
|
||||||
|
);
|
||||||
|
IMAGE_SECTION_HEADER;
|
||||||
|
// 如果文件长度不够,则先扩容
|
||||||
|
let file_size = save_file.metadata().unwrap().len();
|
||||||
|
if file_size < section_foa + section_size_align as u64 {
|
||||||
|
// 文件指针要移动到末尾
|
||||||
|
save_file.seek(std::io::SeekFrom::End(0))?;
|
||||||
|
save_file.set_len(section_foa + section_size_align as u64)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
save_file.seek(std::io::SeekFrom::Start(section_foa))?;
|
||||||
|
save_file.write_all(unsafe {
|
||||||
|
std::slice::from_raw_parts(data_buf as *const u8, section_size_align as usize)
|
||||||
|
})?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 6. 关闭进程
|
||||||
|
unsafe {
|
||||||
|
CloseHandle(h_process).unwrap();
|
||||||
|
};
|
||||||
|
// 7. 返回
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
// 来个测试
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
#[test]
|
||||||
|
fn test_get_process_list() {
|
||||||
|
let process_list = get_process_list();
|
||||||
|
for (name, pid) in process_list {
|
||||||
|
println!("进程名: {}, PID: {}", name, pid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn test_dump_process() {
|
||||||
|
dump_process(11696, "D:\\download\\a.exe").unwrap();
|
||||||
|
}
|
||||||
|
}
|
@ -16,8 +16,8 @@
|
|||||||
"noImplicitAny": false,
|
"noImplicitAny": false,
|
||||||
/* Linting */
|
/* Linting */
|
||||||
"strict": false,
|
"strict": false,
|
||||||
"noUnusedLocals": true,
|
"noUnusedLocals": false,
|
||||||
"noUnusedParameters": true,
|
"noUnusedParameters": false,
|
||||||
"noFallthroughCasesInSwitch": true
|
"noFallthroughCasesInSwitch": true
|
||||||
},
|
},
|
||||||
"include": ["src"],
|
"include": ["src"],
|
||||||
|
Loading…
Reference in New Issue
Block a user