feat: 增加节区、关闭文件
This commit is contained in:
parent
d8b49c12d1
commit
7346f40592
@ -25,6 +25,10 @@ pub enum AppError {
|
|||||||
/// 无法修改文件
|
/// 无法修改文件
|
||||||
#[error("无法修改文件!: {0}")]
|
#[error("无法修改文件!: {0}")]
|
||||||
CannotModifyFile(String),
|
CannotModifyFile(String),
|
||||||
|
|
||||||
|
/// 节名过长
|
||||||
|
#[error("节名过长!")]
|
||||||
|
SectionNameTooLong,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl serde::Serialize for AppError {
|
impl serde::Serialize for AppError {
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
use memmap2::Mmap;
|
use std::io::Seek;
|
||||||
|
use std::option;
|
||||||
|
|
||||||
use crate::app_error::AppError;
|
use crate::app_error::AppError;
|
||||||
use crate::{pe_parse::pe::ReadOnlyPE, services::file};
|
use crate::{pe_parse::pe::ReadOnlyPE, services::file};
|
||||||
|
use memmap2::{Mmap, MmapOptions};
|
||||||
|
|
||||||
/// 应用的状态结构体
|
/// 应用的状态结构体
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
@ -10,7 +13,7 @@ pub struct AppState {
|
|||||||
/// 文件Mmap的只读内存映射
|
/// 文件Mmap的只读内存映射
|
||||||
mmap: Option<Mmap>,
|
mmap: Option<Mmap>,
|
||||||
/// 文件是否是64位
|
/// 文件是否是64位
|
||||||
pub is_64_bit: Option<bool>
|
pub is_64_bit: Option<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AppState {
|
impl AppState {
|
||||||
@ -24,6 +27,14 @@ impl AppState {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// close_file 关闭文件
|
||||||
|
pub fn close_file(&mut self) -> Result<(), AppError> {
|
||||||
|
self.file_path = None;
|
||||||
|
self.mmap = None;
|
||||||
|
self.is_64_bit = None;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
/// 获取文件内存映射的引用
|
/// 获取文件内存映射的引用
|
||||||
pub fn get_mmap_ref(&self) -> Result<&Mmap, AppError> {
|
pub fn get_mmap_ref(&self) -> Result<&Mmap, AppError> {
|
||||||
self.mmap.as_ref().ok_or(AppError::NoFileOpened)
|
self.mmap.as_ref().ok_or(AppError::NoFileOpened)
|
||||||
@ -50,4 +61,216 @@ impl AppState {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
/// 添加节
|
||||||
|
pub fn add_section(
|
||||||
|
&mut self,
|
||||||
|
section_name: &str,
|
||||||
|
section_size: usize,
|
||||||
|
section_characteristics: u32,
|
||||||
|
) -> Result<(), AppError> {
|
||||||
|
// 1. section_name不能超过8个字符
|
||||||
|
if section_name.len() > 8 {
|
||||||
|
return Err(AppError::SectionNameTooLong);
|
||||||
|
}
|
||||||
|
// as_bytes 没有补0
|
||||||
|
let mut section_name_bytes = [0u8; 8];
|
||||||
|
// 循环拷贝section_name的数据
|
||||||
|
for i in 0..section_name.len() {
|
||||||
|
if i < section_name.len() {
|
||||||
|
section_name_bytes[i] = section_name.as_bytes()[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 判断是否可以添加节
|
||||||
|
// if(size_of_headers - 最后一个节表的偏移 - 40) >= 40,则可以添加节表。
|
||||||
|
// 2. 获取size_of_headers
|
||||||
|
let mmap = self.get_mmap_ref()?;
|
||||||
|
let origin_file_len = mmap.len();
|
||||||
|
let optional_header = mmap.get_optional_header()?;
|
||||||
|
let file_header_offset = mmap.get_file_header_offset()?;
|
||||||
|
let optional_header_offset = mmap.get_optional_header_offset()?;
|
||||||
|
let file_header = mmap.get_file_header()?;
|
||||||
|
let size_of_headers = match optional_header {
|
||||||
|
crate::pe_parse::header::ImageOptionalHeader::OptionalHeader32(
|
||||||
|
image_optional_header32,
|
||||||
|
) => image_optional_header32.size_of_headers,
|
||||||
|
crate::pe_parse::header::ImageOptionalHeader::OptionalHeader64(
|
||||||
|
image_optional_header64,
|
||||||
|
) => image_optional_header64.size_of_headers,
|
||||||
|
};
|
||||||
|
let section_table_offset = mmap.get_section_headers_offset()?;
|
||||||
|
// 获取节表的数量
|
||||||
|
let number_of_sections = file_header.number_of_sections;
|
||||||
|
// 1. 获取偏移
|
||||||
|
let section_alignment = match optional_header {
|
||||||
|
crate::pe_parse::header::ImageOptionalHeader::OptionalHeader32(
|
||||||
|
image_optional_header32,
|
||||||
|
) => image_optional_header32.section_alignment,
|
||||||
|
crate::pe_parse::header::ImageOptionalHeader::OptionalHeader64(
|
||||||
|
image_optional_header64,
|
||||||
|
) => image_optional_header64.section_alignment,
|
||||||
|
};
|
||||||
|
|
||||||
|
// 3. 判断是否可以添加节表
|
||||||
|
let section_table_size = 40 * number_of_sections as usize;
|
||||||
|
// TODO: 这里有问题
|
||||||
|
// 要判断第一个节表的pointer_to_raw_data - size_of_headers是否大于40
|
||||||
|
let first_section_header_offset = section_table_offset;
|
||||||
|
let first_pointer_to_raw_data = u32::from_le_bytes(
|
||||||
|
mmap[first_section_header_offset + 20..first_section_header_offset + 24]
|
||||||
|
.try_into()
|
||||||
|
.unwrap(),
|
||||||
|
);
|
||||||
|
|
||||||
|
if first_pointer_to_raw_data - size_of_headers < 40 {
|
||||||
|
// 需要看一下是否可以拓展文件大小
|
||||||
|
|
||||||
|
// 2. 计算size_of_headers对齐之后的大小 例如:0x400 -> 0x1000
|
||||||
|
let aligned_size_of_headers =
|
||||||
|
(size_of_headers + section_alignment - 1) & !(section_alignment - 1);
|
||||||
|
// 可以拓展的大小: 对齐之后的大小 - size_of_headers
|
||||||
|
let expand_size = aligned_size_of_headers - size_of_headers;
|
||||||
|
if expand_size < 40 {
|
||||||
|
// 如果可以拓展的大小小于40,则无法添加节表
|
||||||
|
return Err(AppError::CannotModifyFile("无法拓展文件大小!".to_string()));
|
||||||
|
}
|
||||||
|
// 3. 拓展文件大小
|
||||||
|
// 1. 打开文件
|
||||||
|
let mut file = std::fs::OpenOptions::new()
|
||||||
|
.read(true)
|
||||||
|
.write(true)
|
||||||
|
.open(self.file_path.as_ref().ok_or(AppError::NoFileOpened)?)?;
|
||||||
|
// 设置游标到文件末尾
|
||||||
|
file.seek(std::io::SeekFrom::End(0))?;
|
||||||
|
// 2. 拓展文件大小
|
||||||
|
file.set_len(file.metadata()?.len() + expand_size as u64)?;
|
||||||
|
|
||||||
|
// 2. 映射文件
|
||||||
|
let mut rw_mmap = unsafe {
|
||||||
|
MmapOptions::new()
|
||||||
|
.map_mut(&file)
|
||||||
|
.map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))?
|
||||||
|
};
|
||||||
|
// 循环拷贝数据 把size_of_headers之后的数据往后移动expand_size
|
||||||
|
for i in (size_of_headers as usize..origin_file_len).rev() {
|
||||||
|
rw_mmap[i + expand_size as usize] = rw_mmap[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
// 把[size_of_headers, size_of_headers + expand_size]的数据清零
|
||||||
|
for i in size_of_headers as usize..(size_of_headers as usize + expand_size as usize - 1)
|
||||||
|
{
|
||||||
|
rw_mmap[i] = 0;
|
||||||
|
}
|
||||||
|
// 修整所有节的pointer_to_raw_data
|
||||||
|
for i in 0..number_of_sections {
|
||||||
|
let section_header_offset = section_table_offset + 40 * i as usize;
|
||||||
|
let pointer_to_raw_data = u32::from_le_bytes(
|
||||||
|
rw_mmap[section_header_offset + 20..section_header_offset + 24]
|
||||||
|
.try_into()
|
||||||
|
.unwrap(),
|
||||||
|
);
|
||||||
|
rw_mmap[section_header_offset + 20..section_header_offset + 24]
|
||||||
|
.copy_from_slice(&(pointer_to_raw_data + expand_size as u32).to_le_bytes());
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: 修改SizeOfImage
|
||||||
|
let origin_size_of_image = unsafe {
|
||||||
|
// 在0x38的位置
|
||||||
|
u32::from_le_bytes(
|
||||||
|
rw_mmap[optional_header_offset + 0x38..optional_header_offset + 0x3C]
|
||||||
|
.try_into()
|
||||||
|
.unwrap(),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
let add_image_size = (expand_size + section_alignment - 1) & !(section_alignment - 1);
|
||||||
|
|
||||||
|
rw_mmap[optional_header_offset + 0x38..optional_header_offset + 0x3C]
|
||||||
|
.copy_from_slice(&(origin_size_of_image + add_image_size as u32).to_le_bytes());
|
||||||
|
|
||||||
|
rw_mmap.flush()?;
|
||||||
|
// 3. 重新映射文件
|
||||||
|
self.mmap = Some(file::mmap_file(self.file_path.as_ref().unwrap())?);
|
||||||
|
}
|
||||||
|
// 4. 添加节表
|
||||||
|
// 新的节区文件偏移是文件末尾
|
||||||
|
// TODO: 如果增加的大小为0是否有问题?
|
||||||
|
let new_section_offset = self.get_mmap_ref()?.len();
|
||||||
|
let new_section_header_offset = section_table_offset + section_table_size;
|
||||||
|
{
|
||||||
|
// 拓展文件大小
|
||||||
|
let mut file = std::fs::OpenOptions::new()
|
||||||
|
.read(true)
|
||||||
|
.write(true)
|
||||||
|
.open(self.file_path.as_ref().ok_or(AppError::NoFileOpened)?)?;
|
||||||
|
// 设置游标到文件末尾
|
||||||
|
file.seek(std::io::SeekFrom::End(0))?;
|
||||||
|
// 2. 拓展文件大小
|
||||||
|
file.set_len(file.metadata()?.len() + section_size as u64)?;
|
||||||
|
}
|
||||||
|
// 写入节表数据
|
||||||
|
let mut rw_mmap = file::mmap_file_rw(self.file_path.as_ref().unwrap())?;
|
||||||
|
// 1. 写入节表数据
|
||||||
|
// 1.1 写入节名
|
||||||
|
rw_mmap[new_section_header_offset..new_section_header_offset + 8]
|
||||||
|
.copy_from_slice(§ion_name_bytes);
|
||||||
|
// 写入节的VA
|
||||||
|
// TODO: 新节的VA应该是最后一个节的VA + section_size对齐后的大小
|
||||||
|
let last_section_header_offset =
|
||||||
|
section_table_offset + 40 * (number_of_sections - 1) as usize;
|
||||||
|
let last_section_va = u32::from_le_bytes(
|
||||||
|
rw_mmap[last_section_header_offset + 12..last_section_header_offset + 16]
|
||||||
|
.try_into()
|
||||||
|
.unwrap(),
|
||||||
|
);
|
||||||
|
// 对齐后的VA, 对齐方式(last_section_va + section_size) 和section_alignment进行对齐
|
||||||
|
let aligned_va = (last_section_va + section_size as u32 + section_alignment - 1)
|
||||||
|
& !(section_alignment - 1);
|
||||||
|
|
||||||
|
rw_mmap[new_section_header_offset + 12..new_section_header_offset + 16]
|
||||||
|
.copy_from_slice(&aligned_va.to_le_bytes());
|
||||||
|
|
||||||
|
// 写入新节的size_of_raw_data
|
||||||
|
rw_mmap[new_section_header_offset + 16..new_section_header_offset + 20]
|
||||||
|
.copy_from_slice(&(section_size as u32).to_le_bytes());
|
||||||
|
|
||||||
|
// 写入新节的PointerToRawData
|
||||||
|
rw_mmap[new_section_header_offset + 20..new_section_header_offset + 24]
|
||||||
|
.copy_from_slice(&(new_section_offset as u32).to_le_bytes());
|
||||||
|
|
||||||
|
// 1.4 写入节的特征
|
||||||
|
rw_mmap[new_section_header_offset + 36..new_section_header_offset + 40]
|
||||||
|
.copy_from_slice(§ion_characteristics.to_le_bytes());
|
||||||
|
|
||||||
|
// 修改文件头的节表数量
|
||||||
|
rw_mmap[file_header_offset + 2..file_header_offset + 4]
|
||||||
|
.copy_from_slice(&(number_of_sections + 1).to_le_bytes());
|
||||||
|
|
||||||
|
// 修改size_of_headers的大小
|
||||||
|
let new_size_of_headers = size_of_headers + 40;
|
||||||
|
rw_mmap[optional_header_offset + 0x3C..optional_header_offset + 0x40]
|
||||||
|
.copy_from_slice(&new_size_of_headers.to_le_bytes());
|
||||||
|
|
||||||
|
// TODO: 修改SizeOfImage
|
||||||
|
let origin_size_of_image = unsafe {
|
||||||
|
// 在0x38的位置
|
||||||
|
u32::from_le_bytes(
|
||||||
|
rw_mmap[optional_header_offset + 0x38..optional_header_offset + 0x3C]
|
||||||
|
.try_into()
|
||||||
|
.unwrap(),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
// TODO: 增加的大小应该是section_size对齐后的大小
|
||||||
|
let add_image_size =
|
||||||
|
(section_size as u32 + section_alignment - 1) & !(section_alignment - 1);
|
||||||
|
|
||||||
|
rw_mmap[optional_header_offset + 0x38..optional_header_offset + 0x3C]
|
||||||
|
.copy_from_slice(&(origin_size_of_image + add_image_size).to_le_bytes());
|
||||||
|
|
||||||
|
rw_mmap.flush()?;
|
||||||
|
|
||||||
|
// 2. 重新映射文件
|
||||||
|
self.mmap = Some(file::mmap_file(self.file_path.as_ref().unwrap())?);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -43,6 +43,13 @@ pub fn command_open_file(
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 命令,关闭文件
|
||||||
|
#[tauri::command]
|
||||||
|
pub fn command_close_file(app_state: State<'_, Mutex<AppState>>) -> Result<(), AppError> {
|
||||||
|
app_state.lock().unwrap().close_file()?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
#[tauri::command(async)]
|
#[tauri::command(async)]
|
||||||
pub fn command_get_file_pe_node_tree_data(
|
pub fn command_get_file_pe_node_tree_data(
|
||||||
app_state: State<'_, Mutex<AppState>>,
|
app_state: State<'_, Mutex<AppState>>,
|
||||||
@ -180,4 +187,18 @@ pub fn command_write_data(
|
|||||||
let mut app_state = app_state.lock().unwrap();
|
let mut app_state = app_state.lock().unwrap();
|
||||||
app_state.write_data(offset, &data)?;
|
app_state.write_data(offset, &data)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 命令,添加节
|
||||||
|
#[tauri::command]
|
||||||
|
pub fn command_add_section(
|
||||||
|
app_state: State<'_, Mutex<AppState>>,
|
||||||
|
section_name: String,
|
||||||
|
section_size: usize,
|
||||||
|
section_characteristics: u32,
|
||||||
|
) -> Result<(), AppError> {
|
||||||
|
let mut app_state = app_state.lock().unwrap();
|
||||||
|
app_state.add_section(§ion_name, section_size, section_characteristics)?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
@ -17,6 +17,7 @@ pub fn run() {
|
|||||||
.invoke_handler(tauri::generate_handler![
|
.invoke_handler(tauri::generate_handler![
|
||||||
commands::set_complete,
|
commands::set_complete,
|
||||||
commands::command_open_file,
|
commands::command_open_file,
|
||||||
|
commands::command_close_file,
|
||||||
commands::command_get_file_pe_node_tree_data,
|
commands::command_get_file_pe_node_tree_data,
|
||||||
commands::command_get_pe_data_dos_header,
|
commands::command_get_pe_data_dos_header,
|
||||||
commands::command_get_pe_data_nt_header,
|
commands::command_get_pe_data_nt_header,
|
||||||
@ -24,6 +25,7 @@ pub fn run() {
|
|||||||
commands::command_get_pe_data_optional_header,
|
commands::command_get_pe_data_optional_header,
|
||||||
commands::command_get_pe_data_section_headers,
|
commands::command_get_pe_data_section_headers,
|
||||||
commands::command_write_data,
|
commands::command_write_data,
|
||||||
|
commands::command_add_section,
|
||||||
])
|
])
|
||||||
.setup(|app| {
|
.setup(|app| {
|
||||||
app.manage(Mutex::new(app_state::AppState::default()));
|
app.manage(Mutex::new(app_state::AppState::default()));
|
||||||
|
@ -103,14 +103,14 @@ pub trait ReadOnlyPE: Deref<Target = [u8]> + Sized {
|
|||||||
};
|
};
|
||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
|
/// 获取可选头的偏移
|
||||||
fn get_optional_header_offset(&self) -> Result<usize, PEParseError> {
|
fn get_optional_header_offset(&self) -> Result<usize, PEParseError> {
|
||||||
let file_header_offset = self.get_file_header_offset()?;
|
let file_header_offset = self.get_file_header_offset()?;
|
||||||
let optional_header_offset = file_header_offset + std::mem::size_of::<ImageFileHeader>();
|
let optional_header_offset = file_header_offset + std::mem::size_of::<ImageFileHeader>();
|
||||||
Ok(optional_header_offset)
|
Ok(optional_header_offset)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取节区头的偏移
|
/// 获取节区头的偏移
|
||||||
fn get_section_headers_offset(&self) -> Result<usize, PEParseError> {
|
fn get_section_headers_offset(&self) -> Result<usize, PEParseError> {
|
||||||
// 节区头偏移在可选头之后,可选头大小是可变的,所以需要计算
|
// 节区头偏移在可选头之后,可选头大小是可变的,所以需要计算
|
||||||
let optional_header_size = self.get_size_of_optional_header()?;
|
let optional_header_size = self.get_size_of_optional_header()?;
|
||||||
|
@ -18,4 +18,4 @@ pub fn mmap_file_rw(file_path: &str) -> Result<MmapMut, std::io::Error> {
|
|||||||
.map_mut(&file)
|
.map_mut(&file)
|
||||||
.map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))
|
.map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -260,17 +260,16 @@ export default function DosHeader() {
|
|||||||
];
|
];
|
||||||
|
|
||||||
const handleSave = (item: DataType) => {
|
const handleSave = (item: DataType) => {
|
||||||
console.log("handleSave", item);
|
|
||||||
if (!checkEditValue(item)) {
|
if (!checkEditValue(item)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const bufs = formatEditValue(item);
|
const bufs = formatEditValue(item);
|
||||||
console.log("change value", bufs);
|
console.log("bufs", bufs, item);
|
||||||
invoke("command_write_data", {
|
invoke("command_write_data", {
|
||||||
offset: item.offset,
|
offset: item.offset,
|
||||||
data: bufs,
|
data: bufs,
|
||||||
})
|
})
|
||||||
.then((res) => {
|
.then((_res) => {
|
||||||
// 提示
|
// 提示
|
||||||
success();
|
success();
|
||||||
getData();
|
getData();
|
||||||
|
@ -218,6 +218,8 @@ export default function NodeTableComponent(props: NodeTableComponentProps) {
|
|||||||
size: cloneData[key].array_element_size,
|
size: cloneData[key].array_element_size,
|
||||||
value: resData.fields[key][i],
|
value: resData.fields[key][i],
|
||||||
key: `${key}[${i}]`,
|
key: `${key}[${i}]`,
|
||||||
|
data_type: "hex",
|
||||||
|
array_field: `${key}`
|
||||||
};
|
};
|
||||||
array.push(item);
|
array.push(item);
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,24 @@
|
|||||||
.NodeTableComponentRootFlex {
|
.NodeTableComponentRootFlex {
|
||||||
min-width: calc(100% - 16px);
|
min-width: calc(100% - 16px);
|
||||||
}
|
}
|
||||||
|
|
||||||
.NodeTableComponentTable{
|
.NodeTableComponentTable {
|
||||||
height: calc(100% - 16px);
|
height: calc(100% - 16px);
|
||||||
}
|
}
|
||||||
|
|
||||||
.content{
|
.content {
|
||||||
// 垂直flex
|
// 垂直flex
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
.tableItem {
|
.tableItem {
|
||||||
margin-bottom: 24px;
|
margin-bottom: 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.optionContainer {
|
||||||
|
display: flex;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
.optionItem {
|
||||||
|
margin-right: 16px;
|
||||||
|
}
|
||||||
|
@ -1,10 +1,21 @@
|
|||||||
import NodeTableComponent, {
|
import NodeTableComponent, {
|
||||||
DataTemplateInterface,
|
DataTemplateInterface,
|
||||||
} from "../NodeTableComponent/NodeTableComponent";
|
} from "../NodeTableComponent/NodeTableComponent";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useMemo, useState } from "react";
|
||||||
import { invoke } from "@tauri-apps/api/core";
|
import { invoke } from "@tauri-apps/api/core";
|
||||||
import styles from "./SectionHeaders.module.scss";
|
import styles from "./SectionHeaders.module.scss";
|
||||||
import { Flex } from "antd";
|
import {
|
||||||
|
Flex,
|
||||||
|
Button,
|
||||||
|
Modal,
|
||||||
|
Form,
|
||||||
|
Input,
|
||||||
|
InputNumber,
|
||||||
|
Select,
|
||||||
|
message,
|
||||||
|
} from "antd";
|
||||||
|
import { PlusOutlined, EditOutlined } from "@ant-design/icons";
|
||||||
|
|
||||||
const dataTemplate: DataTemplateInterface = {
|
const dataTemplate: DataTemplateInterface = {
|
||||||
name: {
|
name: {
|
||||||
name: "name",
|
name: "name",
|
||||||
@ -77,11 +88,163 @@ const dataTemplate: DataTemplateInterface = {
|
|||||||
description: "属性",
|
description: "属性",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
// 节区属性
|
||||||
|
const sectionCharacteristics = [
|
||||||
|
{
|
||||||
|
value: 0x80000000,
|
||||||
|
label: "可写",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 0x40000000,
|
||||||
|
label: "可读",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 0x20000000,
|
||||||
|
label: "可执行",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 0x02000000,
|
||||||
|
label: "可丢弃",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 0x04000000,
|
||||||
|
label: "不可缓存",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 0x08000000,
|
||||||
|
label: "不可分页",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 0x10000000,
|
||||||
|
label: "可共享",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 0x01000000,
|
||||||
|
label: "包含扩展重定位",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 0x00000020,
|
||||||
|
label: "包含可执行代码",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 0x00000040,
|
||||||
|
label: "包含已初始化数据",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 0x00000080,
|
||||||
|
label: "包含未初始化数据",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 0x00000200,
|
||||||
|
label: "包含注释或信息",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 0x00000800,
|
||||||
|
label: "将不会成为镜像的一部分",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 0x00001000,
|
||||||
|
label: "包含 COMDAT 数据",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 0x00100000,
|
||||||
|
label: "数据对齐到 1 字节边界",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 0x00200000,
|
||||||
|
label: "数据对齐到 2 字节边界",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 0x00300000,
|
||||||
|
label: "数据对齐到 4 字节边界",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 0x00400000,
|
||||||
|
label: "数据对齐到 8 字节边界",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 0x00500000,
|
||||||
|
label: "数据对齐到 16 字节边界",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 0x00600000,
|
||||||
|
label: "数据对齐到 32 字节边界",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 0x00700000,
|
||||||
|
label: "数据对齐到 64 字节边界",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 0x00800000,
|
||||||
|
label: "数据对齐到 128 字节边界",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 0x00900000,
|
||||||
|
label: "数据对齐到 256 字节边界",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 0x00A00000,
|
||||||
|
label: "数据对齐到 512 字节边界",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 0x00B00000,
|
||||||
|
label: "数据对齐到 1024 字节边界",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 0x00C00000,
|
||||||
|
label: "数据对齐到 2048 字节边界",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 0x00D00000,
|
||||||
|
label: "数据对齐到 4096 字节边界",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 0x00E00000,
|
||||||
|
label: "数据对齐到 8192 字节边界",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 0x00F00000,
|
||||||
|
label: "数据对齐掩码",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 0x00000001,
|
||||||
|
label: "预留:DSECT 类型",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 0x00000002,
|
||||||
|
label: "预留:不加载",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 0x00000004,
|
||||||
|
label: "预留:组节区",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 0x00000008,
|
||||||
|
label: "预留:不填充节区",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 0x00000010,
|
||||||
|
label: "预留:COPY 类型",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 0x00000100,
|
||||||
|
label: "预留:其他链接信息",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 0x00000400,
|
||||||
|
label: "预留:覆盖节区",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
// 节区头大小
|
// 节区头大小
|
||||||
const sectionHeaderSize = 40;
|
const sectionHeaderSize = 40;
|
||||||
|
|
||||||
export default function SectionHeaders() {
|
export default function SectionHeaders() {
|
||||||
const [data, setData] = useState([]);
|
const [data, setData] = useState([]);
|
||||||
|
const [addSectionVisible, setAddSectionVisible] = useState(false);
|
||||||
|
const [addSectionLoading, setAddSectionLoading] = useState(false);
|
||||||
|
const [addSectionForm] = Form.useForm();
|
||||||
|
|
||||||
const command = "command_get_pe_data_section_headers";
|
const command = "command_get_pe_data_section_headers";
|
||||||
|
|
||||||
@ -128,13 +291,129 @@ export default function SectionHeaders() {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
const requestAddSection = async (
|
||||||
|
sectionName: string,
|
||||||
|
sectionSize: number,
|
||||||
|
sectionCharacteristics: number
|
||||||
|
) =>
|
||||||
|
invoke("command_add_section", {
|
||||||
|
sectionName,
|
||||||
|
sectionSize,
|
||||||
|
sectionCharacteristics,
|
||||||
|
});
|
||||||
|
|
||||||
|
const AddSectionModel = useMemo(() => {
|
||||||
|
const handelOk = () => {
|
||||||
|
const { name, size, characteristics } = addSectionForm.getFieldsValue();
|
||||||
|
console.log(
|
||||||
|
"send",
|
||||||
|
name,
|
||||||
|
size,
|
||||||
|
characteristics.reduce((a, b) => a + b)
|
||||||
|
);
|
||||||
|
setAddSectionLoading(true);
|
||||||
|
requestAddSection(
|
||||||
|
name,
|
||||||
|
size,
|
||||||
|
characteristics.reduce((a, b) => a + b)
|
||||||
|
)
|
||||||
|
.then((_res) => {
|
||||||
|
requestData();
|
||||||
|
setAddSectionLoading(false);
|
||||||
|
setAddSectionVisible(false);
|
||||||
|
})
|
||||||
|
.catch((_err) => {
|
||||||
|
setAddSectionLoading(false);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal
|
||||||
|
title="添加节"
|
||||||
|
open={addSectionVisible}
|
||||||
|
onOk={handelOk}
|
||||||
|
loading={addSectionLoading}
|
||||||
|
onCancel={() => setAddSectionVisible(false)}
|
||||||
|
>
|
||||||
|
<Form
|
||||||
|
form={addSectionForm}
|
||||||
|
name="control-hooks"
|
||||||
|
onFinish={(values) => {
|
||||||
|
console.log(values);
|
||||||
|
}}
|
||||||
|
style={{ maxWidth: 600 }}
|
||||||
|
>
|
||||||
|
<Form.Item
|
||||||
|
name="name"
|
||||||
|
label="节区名"
|
||||||
|
rules={[{ required: true, type: "string", max: 8 }]}
|
||||||
|
>
|
||||||
|
<Input />
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item
|
||||||
|
name="size"
|
||||||
|
label="大小"
|
||||||
|
rules={[{ required: true, type: "number" }]}
|
||||||
|
>
|
||||||
|
<InputNumber min={0} />
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item
|
||||||
|
name="characteristics"
|
||||||
|
label="属性"
|
||||||
|
rules={[{ required: true }]}
|
||||||
|
>
|
||||||
|
<Select
|
||||||
|
mode="multiple"
|
||||||
|
style={{ width: "100%" }}
|
||||||
|
placeholder="Please select"
|
||||||
|
>
|
||||||
|
{sectionCharacteristics.map((item) => {
|
||||||
|
return (
|
||||||
|
<Select.Option value={item.value}>
|
||||||
|
{item.label}-0x{item.value.toString(16).toUpperCase()}
|
||||||
|
</Select.Option>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</Select>
|
||||||
|
</Form.Item>
|
||||||
|
</Form>
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
}, [addSectionVisible, addSectionLoading]);
|
||||||
|
|
||||||
|
const requestData = () => {
|
||||||
invoke(command).then((res) => {
|
invoke(command).then((res) => {
|
||||||
setData(formatDataHandler(res));
|
setData(formatDataHandler(res));
|
||||||
});
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
requestData();
|
||||||
}, []);
|
}, []);
|
||||||
return (
|
return (
|
||||||
<Flex className={styles.content}>
|
<Flex className={styles.content}>
|
||||||
|
{AddSectionModel}
|
||||||
|
<Flex className={styles.optionContainer}>
|
||||||
|
<Button
|
||||||
|
type="primary"
|
||||||
|
icon={<PlusOutlined />}
|
||||||
|
onClick={() => setAddSectionVisible(true)}
|
||||||
|
className={styles.optionItem}
|
||||||
|
>
|
||||||
|
添加节
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
type="primary"
|
||||||
|
icon={<EditOutlined />}
|
||||||
|
className={styles.optionItem}
|
||||||
|
onClick={() => {
|
||||||
|
message.info("还没有实现!");
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
扩展最后一节大小
|
||||||
|
</Button>
|
||||||
|
</Flex>
|
||||||
|
|
||||||
{data.map((item, index) => {
|
{data.map((item, index) => {
|
||||||
return (
|
return (
|
||||||
<div className={styles.tableItem}>
|
<div className={styles.tableItem}>
|
||||||
|
@ -4,7 +4,7 @@ import { Layout, Flex, Button, Empty } from "antd";
|
|||||||
import { listen } from "@tauri-apps/api/event";
|
import { listen } from "@tauri-apps/api/event";
|
||||||
import { invoke } from "@tauri-apps/api/core";
|
import { invoke } from "@tauri-apps/api/core";
|
||||||
const { Content } = Layout;
|
const { Content } = Layout;
|
||||||
import { SaveOutlined, FolderOpenFilled } from "@ant-design/icons";
|
import { CloseOutlined, FolderOpenFilled } from "@ant-design/icons";
|
||||||
import SiderTree from "../components/side_tree/SideTree";
|
import SiderTree from "../components/side_tree/SideTree";
|
||||||
import DosHeader from "../components/DosHeader/DosHeader";
|
import DosHeader from "../components/DosHeader/DosHeader";
|
||||||
import NtHeader from "../components/NTHeader/NTHeader";
|
import NtHeader from "../components/NTHeader/NTHeader";
|
||||||
@ -36,6 +36,14 @@ export default function MainPage() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const closeFile = async () => {
|
||||||
|
invoke("command_close_file").then(() => {
|
||||||
|
setFilePath("");
|
||||||
|
setTreeData([]);
|
||||||
|
setSelectedKey("");
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const changeFile = (filePath: string) => {
|
const changeFile = (filePath: string) => {
|
||||||
invoke("command_open_file", { filePath }).then(() => {
|
invoke("command_open_file", { filePath }).then(() => {
|
||||||
invoke("command_get_file_pe_node_tree_data").then((res) => {
|
invoke("command_get_file_pe_node_tree_data").then((res) => {
|
||||||
@ -74,20 +82,27 @@ export default function MainPage() {
|
|||||||
style={{
|
style={{
|
||||||
marginRight: "10px",
|
marginRight: "10px",
|
||||||
}}
|
}}
|
||||||
type="dashed"
|
type="primary"
|
||||||
|
color="primary"
|
||||||
onClick={openFile}
|
onClick={openFile}
|
||||||
icon={<FolderOpenFilled></FolderOpenFilled>}
|
icon={<FolderOpenFilled></FolderOpenFilled>}
|
||||||
>
|
>
|
||||||
打开新文件
|
打开新文件
|
||||||
</Button>
|
</Button>
|
||||||
<Button type="primary" icon={<SaveOutlined></SaveOutlined>}>
|
{/* 关闭文件 */}
|
||||||
保存
|
<Button
|
||||||
|
danger
|
||||||
|
type="dashed"
|
||||||
|
color="danger"
|
||||||
|
icon={<CloseOutlined></CloseOutlined>}
|
||||||
|
onClick={closeFile}
|
||||||
|
>
|
||||||
|
关闭文件
|
||||||
</Button>
|
</Button>
|
||||||
</Flex>
|
</Flex>
|
||||||
<Flex className={styles.mainContent}>
|
<Flex className={styles.mainContent}>
|
||||||
<Flex className={styles.sider}>
|
<Flex className={styles.sider}>
|
||||||
<SiderTree
|
<SiderTree
|
||||||
|
|
||||||
treeData={treeData}
|
treeData={treeData}
|
||||||
defaultSelectedKey={treeData[0]?.key || ""}
|
defaultSelectedKey={treeData[0]?.key || ""}
|
||||||
onSelect={onSelect}
|
onSelect={onSelect}
|
||||||
@ -97,9 +112,12 @@ export default function MainPage() {
|
|||||||
{selectedKey && SelectNodeMap[selectedKey] ? (
|
{selectedKey && SelectNodeMap[selectedKey] ? (
|
||||||
SelectNodeMap[selectedKey]
|
SelectNodeMap[selectedKey]
|
||||||
) : (
|
) : (
|
||||||
<Empty style={{
|
<Empty
|
||||||
alignSelf: "center",
|
style={{
|
||||||
}} description={"请选择一个节点"} />
|
alignSelf: "center",
|
||||||
|
}}
|
||||||
|
description={"请选择一个节点"}
|
||||||
|
/>
|
||||||
)}
|
)}
|
||||||
</Content>
|
</Content>
|
||||||
</Flex>
|
</Flex>
|
||||||
|
Loading…
Reference in New Issue
Block a user