跳转至

基于kvm-qemu使用rust开发一个命令行cheat engine

main

mod ch_3_value_scanner;
mod ch_3_ptr_map;
mod ch_3_disasm;
mod ch_3_sigmaker;


use std::collections::BTreeSet;
use std::sync::mpsc;
use std::sync::mpsc::Receiver;
use std::thread;
use std::time::Instant;
use iced_x86::Decoder;
use scan_fmt::scan_fmt_some;
use simplelog::{LevelFilter, TermLogger, Config, TerminalMode};
use memflow::connector::ConnectorInventory;
use memflow::{Address, CachedMemoryAccess, OsProcessInfo, PartialResultExt, size, VirtualMemory};
use memflow_win32::{Kernel, Win32Process};
use crate::ch_3_ptr_map::PtrMAp;
use crate::ch_3_value_scanner::ValueScanner;
use ch_3_disasm::DisAsm;
use memflow_win32::{Error, Result};
use crate::ch_3_sigmaker::Sigmaker;

const PAGE_SIZE: usize = 4096;

/// ## 修改cli2 程序, 改变其堆上 u64 的内存
fn main() -> Result<()> {
    TermLogger::init(LevelFilter::Info, Config::default(), TerminalMode::Mixed).expect("log 初始化失败");
    unsafe {
        let inventory = ConnectorInventory::scan();
        println!("所有的链接器: {:?}", inventory.available_connectors());
        let connect = inventory.create_connector_default("qemu_procfs")?;

        // 获取kernel相关信息, 运行这里会下载pdb工具, 会很慢(好像也用过不到, 我这里改源码直接return了)
        let mut kernel = Kernel::builder(connect)
            .build_page_cache(|mem, arch| {  // 开启页缓存, 好像没啥差别 和下面默认缓存设置相比
                CachedMemoryAccess::builder(mem)
                    .arch(arch)
                    .build()
                    .unwrap()
            })
            // .build_default_caches()
            .build()?;

        // 获得所有进程
        let process_info = kernel.process_info_list()?;

        // 遍历所有进程的信息
        for process in process_info.iter() {
            println!("{:?} {:?}", process.pid, process.name)
        }

        // 得到指定进程
        let mut process = kernel.process("cli_2.exe")?;
        // let mut process = kernel.process("League of Legends.exe")?;

        // {
        //     // 每 16m 字节合并为一块内存区域
        //     let mem_map = process.virt_mem.virt_page_map(size::mb(16));
        //
        //     for (addr, size) in mem_map.iter() {
        //         println!("block addr {addr:x}, size: {size:x}");
        //     }
        // }

        // 一个反编译汇编器
        let mut dis_asm = DisAsm::default();

        // 一个指针关系表
        let mut ptr_map = PtrMAp::default();

        // 创建一个扫描器
        let mut scanner = ValueScanner::default();

        let mut type_name = String::new();
        let mut buf_len = 0;
        loop {
            let line = get_line();
            let mut tokens = line.trim().splitn(2, " ");
            let (cmd, args) = (tokens.next().unwrap_or(""), tokens.next().unwrap_or(""));

            match cmd {
                "q" => break,
                "p" => {
                    scanner.print_matches(&mut process.virt_mem, buf_len, &type_name);
                    println!("一共有 {} 个: ", scanner.matches_iter().len());
                },
                "a" => {
                    if let (Some(addr)) = scan_fmt_some!(args, "{x}", [hex u64]) {
                        scanner.matches.push(Address::from(addr));
                    };
                }
                "r" => {
                    buf_len = 0;
                    type_name = String::new();
                    ptr_map.reset();
                    dis_asm.reset();
                    scanner.reset();
                }
                "pm" => {
                    ptr_map.reset();
                    ptr_map.create_map(&mut process.virt_mem, process.proc_info.proc_arch.size_addr());

                    // let addr = Address::from(0x1bae1bba350_u64);
                    // let addr = Address::from(0x7ff6ae531040_u64);
                    // ptr_map.walk_down_range(addr, 0, 16, 0, 5);
                }
                "g" => {
                    dis_asm.reset();
                    dis_asm.collect(&mut process);
                    println!("全局变量一共: {:x}", dis_asm.map.len());
                }
                "s" => {
                    // 得到 s 的反汇编代码
                    if let Some(addr) = scan_fmt_some!(args, "{x}", [hex u64]) {
                        match Sigmaker::find_sigs(&mut process, &dis_asm, addr.into()) {
                            Ok(sigs) => {
                                println!("Found signatures:");
                                for sig in sigs {
                                    println!("{}", sig);
                                }
                            }
                            Err(e) => println!("sigmaker error {}", e),
                        }
                    } else {
                        println!("请输入: s{{addr}}");
                    }
                }
                "os" => {  // off scan, 使用 ptr_map 得到 扫描仪扫到的指针 的调用链
                    if let (Some(use_di), Some(lrange), Some(urange), Some(max_depth), filter_args) = scan_fmt_some!(args, "{} {} {} {} {x}", String, usize, usize, usize, [hex u64]) {
                        // 先把 所有使用的指针收集起来
                        if ptr_map.map.is_empty() {
                            ptr_map.create_map(&mut process.virt_mem, process.proc_info.proc_arch.size_addr());
                        }
                        let st = Instant::now();
                        let matches = if use_di == "y" {
                            if dis_asm.map.is_empty() {
                                dis_asm.collect(&mut process);
                            }
                            // 去重得到全局变量列表
                            // let set_global_addrs = &dis_asm.map.values().copied().collect::<BTreeSet<Address>>().iter().copied().collect::<Vec<Address>>();

                            // 得到 全局变量内 指针的调用链, 然后找到scanner内匹配的
                            let tmp_matches = ptr_map.find_matches_addrs(lrange, urange, max_depth, scanner.matches_iter(), &dis_asm.globals);
                            println!("os matchs 找到: {}", tmp_matches.len());
                            tmp_matches
                        } else {
                            // 得到 当前程序所有的 指针的调用链, 然后找到scanner内匹配的
                            let tmp_matches = ptr_map.find_matches(lrange, urange, max_depth, scanner.matches_iter());
                            println!("os matchs 找到: {}", tmp_matches.len());
                            tmp_matches
                        };

                        let end = st.elapsed().as_millis();
                        for (m, offsets) in matches.iter() {
                            // 如果只对 传进来的指定的基地址 感兴趣
                            if let Some(filter) = filter_args {
                                if let Some((f, _)) = offsets.first() {
                                    if f.as_u64() != filter {
                                        continue
                                    }
                                }
                            }
                            for (start, off) in offsets {
                                print!("{start:x} + ({off}) => ")
                            }
                            println!("{m:x}")
                        }
                        println!("找到: {} 用时: {end}ms", matches.len())
                    } else{
                        println!("请输入正确的值: os y/[n] lrange urange max_depth")
                    }
                }
                "w" => {
                    match write_value(args, &type_name, scanner.matches_iter(), &mut process.virt_mem) {
                        Ok(o) => {
                            println!("修改成功");
                        }
                        Err(e) => {
                            println!("修改失败: {e}");
                        }
                    }
                }
                _ => {
                    if let Some((buf, tp)) = parse_input(cmd, args) {
                        type_name = tp;
                        buf_len = buf.len();
                        scanner.scan(&mut process.virt_mem, &buf);
                        println!("一共有 {} 个: ", scanner.matches_iter().len());
                        // scanner.print_matches(&mut process.virt_mem, buf_len, &type_name);
                    } else {
                        println!("无法解析")
                    }
                }
            };
        }
    }

    Ok(())
}

// 得到标准输入
fn get_line() -> String {
    let mut out = String::new();
    std::io::stdin().read_line(&mut out);
    out
}

fn async_get_line() -> Receiver<String> {
    let (tx, rx) = mpsc::channel();
    thread::spawn(move || tx.send(get_line()));
    rx
}

// 解析输入的 参数: i64 123
fn parse_input(type_name: &str, value: &str) -> Option<(Box<[u8]>, String)>{
    let buf = match type_name {
        "str" => Box::from(value.as_bytes()),
        "str_utf16" => {  // utf16 特殊处理这是windows使用的文本格式
            let mut out = vec![];
            for v in value.encode_utf16() {
                out.extend(v.to_ne_bytes().iter().copied())
            }
            out.into_boxed_slice()
        },
        "i64" => Box::from(value.parse::<i64>().unwrap().to_ne_bytes()),
        "u64" => Box::from(value.parse::<u64>().unwrap().to_ne_bytes()),
        "i32" => Box::from(value.parse::<i32>().unwrap().to_ne_bytes()),
        "u32" => Box::from(value.parse::<u32>().unwrap().to_ne_bytes()),
        "i16" => Box::from(value.parse::<i16>().unwrap().to_ne_bytes()),
        "u16" => Box::from(value.parse::<u16>().unwrap().to_ne_bytes()),
        "i8" => Box::from(value.parse::<i8>().unwrap().to_ne_bytes()),
        "u8" => Box::from(value.parse::<u8>().unwrap().to_ne_bytes()),
        "f64" => Box::from(value.parse::<f64>().unwrap().to_ne_bytes()),
        "f32" => Box::from(value.parse::<f32>().unwrap().to_ne_bytes()),
        _ => return None,
    };
    Some((buf, type_name.to_string()))
}

pub fn write_value(args: &str, type_name: &str, matches: &[Address], mut virt_mem: impl VirtualMemory) -> Result<()> {
    let usage = Error::Other("usage: w {{idx/*}} {{o/c}} {{value}}");

    if matches.is_empty() {
        return Err(Error::Other("matches是空的"));
    }

    let mut words = args.splitn(3, " ");
    let (idx, mode, value) = (words.next().ok_or(usage)?, words.next().ok_or(usage)?, words.next().ok_or(usage)?);

    let (skip, take) = if idx == "*" {
        (0, matches.len())
    } else {
        (idx.parse::<usize>().expect("解析idx失败"), 1)
    };

    // 解析要写入的值
    let (v, _) = parse_input(type_name, value).ok_or(Error::Other("解析输入type_name value失败"))?;

    let rx = async_get_line();

    if mode == "o" {
        println!("修改中~");
    } else if mode == "c" {
        println!("修改中~ 按确定键停止");
    } else {
        return Err(Error::Other("错误的修改模式"));
    };
    loop {
        for m in matches.iter().skip(skip).take(take) {
            virt_mem.virt_write_raw(*m, &v).data_part();
        }
        // 如果只修改一次
        if mode == "o" {
            break
        } else {
            // 如果键盘输入, 则停止
            if mode == "c" {
                if let Ok(_) = rx.try_recv() {
                    break
                }
            }
        }
    }
    Ok(())
}

disasm

use std::cmp::{max, min};
use std::collections::BTreeMap;
use memflow::{Address, PartialResultExt, size, VirtualMemory};
use memflow_win32::Win32Process;
use pelite::PeFile;
use iced_x86::{Decoder, DecoderOptions};

#[derive(Default)]
pub struct DisAsm {
    // 保存了全局变量相关
    pub map: BTreeMap<Address, Address>,  // 数据转移指令的ip地址, 数据转移操作的目的地址(其实就是指令地址+偏移地址)
    pub inverse_map: BTreeMap<Address, Vec<Address>>, // 一个全局变量可能被多个 ip的指令使用 保存所以需要一个vec
    pub globals: Vec<Address>  // 保存所有的全局变量,  其实就是不重复的 self.map 中的value
}

impl DisAsm {
    pub fn reset(&mut self) {
        self.map.clear();
        self.inverse_map.clear();
        self.globals.clear();
    }

    /// 扫描全局变量, 扫描模块的每个部分, 找到可执行的代码段, 扫描这些段, 反汇编每一条指令, 保证不会对一行指令反汇编两次, 也不会再某些指令中间开始反汇编
    ///
    pub fn collect(&mut self, process:&mut Win32Process<impl VirtualMemory>) {
        self.reset();

        // 得到进程所有的模块
        let modules = process.module_list().unwrap();

        // 数据标头的buffer , 128kb足够
        let mut image_buffer = vec![0; size::kb(128)];

        for module in modules.iter() {
            // 读取模块的标头的字节数据
            process.virt_mem.virt_read_raw_into(module.base, &mut image_buffer).data_part();

            // 解析为模块头
            let pefile = PeFile::from_bytes(&image_buffer).expect("pe头解析失败");

            // 解析模块所有的段
            for section in pefile.section_headers().iter() {

                // 过滤掉不符合的一些特征的段, 然后扫描整个段内容
                if section.Characteristics & 0x20 != 0 {
                    // 段开始位置, 就是模块在内存中的基础位置 加上 当前段在模块中的开始位置
                    let section_start_addr = module.base.as_u64() + section.VirtualAddress as u64;
                    // 段结束位置, 就是开始位置 + 段大小
                    let section_end_addr = section_start_addr + section.VirtualSize as u64;

                    // 扫描段每次扫描16mb
                    let mut cur_scanner_addr = 0;  // 当前扫描的结束位置
                    let mut chunk_buffer = vec![0; size::mb(16) + 32];  // 预留32个字节给指令
                    for chunk_start in (section_start_addr..section_end_addr).step_by(size::mb(16)) {
                        // 防止越界(这里找指令的边界, 而不是切块的边界)
                        let chunk_start = max(chunk_start, cur_scanner_addr);  // 把当前 16mb内容的开始地址, 和 当前扫描的位置比较找最大的 (有什么用?)(可能是找到跨页的指令?比如 一个指令由于切块, 被分成了两个块中?, 还有就是chunk_buffer, 预留了一些字节, 可能会导致开头的指令重叠取出, 被多次扫描)
                        let chunk_end = min(section_end_addr, chunk_start + size::mb(16) as u64);  // 如果不够16mb, 就有多少读取多少, 而不是取16mb

                        // 读取内存数据
                        process.virt_mem.virt_read_raw_into(chunk_start.into(), &mut chunk_buffer).data_part();

                        // 创建解码器
                        let mut decoder = Decoder::new(process.proc_info.proc_arch.bits().into(), &chunk_buffer, DecoderOptions::NONE);

                        // 设置解码器的ip
                        decoder.set_ip(chunk_start);

                        for (ip, addr) in decoder
                            .iter()
                            .filter(|i| i.ip() < chunk_end)  // 必须小于结束地址
                            .inspect(|i| cur_scanner_addr = i.ip() + i.len() as u64)  // 每次推进 当前已经扫描的位置
                            .filter(|i| i.is_ip_rel_memory_operand())  // 检查内存操作数是否与RIP/EIP相关  得到相对操作数的指令(也就是使用当前ip的 相对地址)
                            .filter(|i| i.near_branch_target() == 0)  // 不是分支调用语句
                            .map(|i| (i.ip(), i.ip_rel_memory_address()))  // (ip, 操作数相对于EIP或RIP寄存器的相对内存操作数,如果该操作数是相对于EIP或RIP寄存器的相对内存操作数,则返回64位的绝对地址)
                        {
                            self.map.insert(ip.into(), addr.into());
                        };

                    };
                }
            }
        }
        // 保存反向指针
        for (k, v) in self.map.iter() {
            let addrs = self.inverse_map.entry(*v).or_default();
            addrs.push(*k);
        }

        // 保存所有ip
        self.globals = self.inverse_map.keys().copied().collect();
        println!("DisAsm size: {}", self.map.len())
    }
}

ptr_map

use std::cmp::Ordering;
use std::collections::{BTreeMap};
use std::ops::Bound::Included;
use memflow::{Address, PartialResultExt, size, VirtualMemory};


#[derive(Default)]
pub struct PtrMAp {
    pub map: BTreeMap<Address, Address>,  //正向的 指针所在的位置 -> 指针指向的实际的值        用来存放当前进程中每个指针的映射
    pub inverse_map: BTreeMap<Address, Vec<Address>>, // 反向指针, 一个地址可能被多个地址保存所以需要一个vec
    pub pointers: Vec<Address>  // 保存了所有的非终点的指针, 其实就是 self.map中不重复的key
}


impl PtrMAp {
    pub fn reset(&mut self) {
        self.map.clear();
        self.inverse_map.clear();
        self.pointers.clear();
    }

    // 循环所有的内存块, 找到符合指针类型的数值, 并做出一个k,v映射
    pub fn create_map<T: VirtualMemory>(&mut self, virt_mem: &mut T, addr_size: usize) {
        self.reset();
        let mem_map = virt_mem.virt_page_map_range(size::mb(16), Address::NULL, (1_usize << 48).into());
        // 循环所有的块
        let mut buf = vec![0; size::kb(64) + addr_size - 1];
        for (block_addr, block_size) in mem_map.iter() {
            // 循环块内内存(每次循环64k)
            for offset in (0..*block_size).step_by(size::kb(64)) {
                // 如果读到数据
                if let Ok(_) = virt_mem.virt_read_raw_into(*block_addr + offset, &mut buf).data_part() {
                    // 循环64k 内部的 数据
                    for (o, data) in buf.windows(addr_size).enumerate(){
                        let addr = *block_addr + offset + o;
                        let out_addr = Address::from(u64::from_le_bytes(data.try_into().unwrap()));

                        // 查看 out_addr 是否是一个内存地址(是否在映射的内存块当中)
                        if let Ok(_) = mem_map
                            .binary_search_by(|&(a, u)| {
                                if a <= out_addr && out_addr <= a + u {
                                    Ordering::Equal
                                } else {
                                    a.cmp(&out_addr)
                                }
                            }) {
                            self.map.insert(addr, out_addr);
                        };
                    }
                }
            }
        }
        // 保存反向指针
        for (k, v) in self.map.iter() {
            let addrs = self.inverse_map.entry(*v).or_default();
            addrs.push(*k);
        }

        // 保存所有非终止点指针
        self.pointers = self.map.keys().copied().collect();
    }

    // 从一个地址addr中递归的查找指针映射表, 直到找到 start_points 搜索列表中符合的指针地址
    fn walk_down_range(&self, addr: Address, lrange: usize, urange: usize, max_levels: usize, level: usize, start_points: &[Address], out: &mut Vec<(Address, Vec<(Address, isize)>)>, (final_addrs, stack): (Address, &mut Vec<(Address, isize)>)) {
        // 从指针地址, 往下找实际保存的value, 如果这个value 的 范围, 还是指针, 则继续往下找 一直找到 max_levels层
        let min = Address::from(addr.as_u64().saturating_sub(urange as _));  // 想要的addr 可能并没有被直接保存, 而是 指针+偏移, 这里减去 up_range, 是因为 计算的 上一级指针的范围, 在平坦内存中, 这个范围 是在指定addr 的 左侧
        let max = Address::from(addr.as_u64().saturating_add(lrange as _));

        // addr 如果如果已经在start_points 上级指针的附近, 会把 进入下面的循环, 把附近指针, 都添加到out中
        // 指向addr的指针列表, 二分查找到 min和max范围中间的所有指针
        let idx = start_points.binary_search(&min).unwrap_or_else(|x| x);
        // 得到 上方 min的idx   到  <= max 的地方  这个范围区间
        let mut iter = start_points.iter().skip(idx).copied().take_while(|&v| v <= max);
        // 把 addr 附近的指针的 和信息都保存起来
        for e in iter {
            let off = signed_diff(addr, e);  // addr附近的e指针 的字节距离
            let mut cloned = stack.clone();  // 得到 已经保存的调用栈
            cloned.push((e, off));  // 把当前 e 和 距离的字节 记录下信息 (push到了最后一个)
            cloned.reverse();  // 翻转一下, 把 最后添加的, 基地址 调换到 第一个,  第一次添加的addr附近的放到最后一个
            out.push((final_addrs, cloned));  // 把 由基地址=>addr 指针调用链, 添加到out, 键就是 外部传入的 终止点指针
        }

        // // 只保存最接近的信息, 找到最接近的指针保存,
        // let mut m = iter.next();
        // for e in iter {
        //     let off = signed_diff(addr, e).abs();
        //     if off < signed_diff(addr, m.unwrap()).abs() {  // 如果当前偏移, 小于 上次循环的地址偏移
        //         m = Some(e);  // 保存当前偏移
        //     }
        // }
        // if let Some(e) = m {
        //     let off = signed_diff(addr, e);
        //     let mut cloned = stack.clone();
        //     cloned.push((e, off));
        //     cloned.reverse();
        //     out.push((final_addrs, cloned));
        // }

        // 查找b树所有的指针, 指定基础范围, 并且不能超过最大递归深度
        if level < max_levels {
            for (k, vec) in self.inverse_map.range((Included(&min), Included(&max))) {  // 循环的 k就是addr附近的被指向的值, vec就是指向k值的指针列表
                let off = signed_diff(addr, *k );  // 在范围内的指针k, 和addr差了具体多少字节
                stack.push((*k, off));  // 压栈
                for v in vec {  // 循环内递归, 又把属于 k值的 上级指针 vec逐个, 传入当前函数, 向上查找 上级的上级指针
                    self.walk_down_range(*v, lrange, urange, max_levels, level + 1, start_points, out, (final_addrs, stack));
                }
                stack.pop();  // 每次循环 k 之后, 还原栈
            };
        }
    }

    // 传进来 scanner扫描到的地址, 递归的寻找指针调用链, 从所有的非终点的指针
    pub fn find_matches(&self, lrange: usize, urange: usize, max_depth: usize, search_for: &Vec<Address>) -> Vec<(Address, Vec<(Address, isize)>)> {
        // 从当前所有的指针映射map中 构造调用链, 然后得到 search_for 内的指针的调用链
        self.find_matches_addrs(lrange, urange, max_depth, search_for, &self.pointers)
    }


    // search_for 中保存了 最终的需要的值的 地址,
    pub fn find_matches_addrs(&self, lrange: usize, urange: usize, max_depth: usize, search_for: &Vec<Address>, entry_points: &Vec<Address>) -> Vec<(Address, Vec<(Address, isize)>)> {
        let mut matches  = vec![];
        // 循环search_for 终止点的指针, 反向查找  entry_points中保存的基地址
        let mut points = entry_points.clone();
        points.sort();
        for m in search_for.iter() {
            self.walk_down_range(*m, lrange, urange, max_depth, 1, &points, &mut matches, (*m, &mut vec![]));  // tmp是外部传入的一个栈, 内部需要递归调用
        }
        matches
    }
}

// 计算两个地址之间的差值, a是否大于b, 是否小于b
pub fn signed_diff(a: Address, b: Address) -> isize {
    a.as_u64()
        .checked_sub(b.as_u64())
        .map(|a| a as isize)
        .unwrap_or_else(|| -((b - a) as isize))
}

sigmaker

// use iced_x86::{Code, ConstantOffsets, Decoder, DecoderOptions, Instruction, OpKind, Register};
// use pelite::PeFile;
// use memflow::{Address, size, VirtualMemory, VirtualReadData};
// use memflow_win32::Win32Process;
// use memflow_win32::error::*;
// use crate::ch_3_disasm::DisAsm;
//
// const MAX_SIG_LEN: usize = 128;
//
// pub struct SigState<'a> {
//     start_ip:Address,
//     buf: &'a [u8; MAX_SIG_LEN], // 对ip后面128字节数据的引用
//     decoder: Decoder<'a>,  // 对应128字节数据的解码器, 所以和buf有一样的生命周期
//     instrs: Vec<(Instruction, ConstantOffsets)>,  //
//     mask: Vec<u8>,
// }
//
// impl SigState<'_> {
//     // 添加一条指令
//     pub fn add_single_instr(&mut self) -> bool {
//         // 如果不能继续解析
//         if self.decoder.can_decode() {
//             return false;
//         }
//         // 解码下一条指令,
//         let instr = self.decoder.decode();
//
//         // 检查指令有效
//         if instr.code() == Code::INVALID {
//             false
//         } else {
//             // 添加掩码
//             let constant_offsets =  self.decoder.get_constant_offsets(&instr);  //当前指令相关信息
//             for _ in 0..instr.len() {
//                 self.mask.push(0xff)
//             };
//             let mask_len = self.mask.len();
//             let instr_mask =&mut self.mask[(mask_len - instr.len())..];  // 当前指令掩码的在self.mask中的引用
//             Self::mask_instr(&instr, &constant_offsets, instr_mask);  // 传递当前指令,当前指令的常量偏移 和当前指令的掩码的引用,
//             self.instrs.push((instr, constant_offsets));
//             true
//         }
//     }
//     fn mask_instr(instr: &Instruction, offsets: &ConstantOffsets, mask: &mut [u8]) {
//         //参数3个: 当前指令,当前指令的常量偏移, 当前指令的掩码的引用(等下直接修改引用就修改了self.mask)
//         // 它的作用是根据给定的指令 (Instruction) 和位移信息 (ConstantOffsets) 修改一个掩码数组 (mask),以便在汇编指令处理中忽略特定部分的指令
//
//         // 检查指令中是否包含特定基础寄存器
//         if let Register::EIP
//         | Register::RIP
//         | Register::ES
//         | Register::CS
//         | Register::SS
//         | Register::DS
//         | Register::FS
//         | Register::GS
//         | Register::None = instr.memory_base()
//         {
//             Self::mask_mem(offsets, mask);
//         };
//
//         // 检查指令中的第一个操作数是否是特定分支类型
//         if let Ok(OpKind::NearBranch16)
//         | Ok(OpKind::NearBranch32)
//         | Ok(OpKind::NearBranch64)
//         | Ok(OpKind::FarBranch16)
//         | Ok(OpKind::FarBranch32) = instr.try_op_kind(0)
//         {
//             // 如果是特定分支类型,调用 mask_branch 函数来修改分支部分的掩码
//             Self::mask_branch(&offsets, mask, 1);
//         }
//     }
//
//     // 将 掩码mask数组  中与位移有关的位设置为无效, 以便在某些操作中忽略位移部分
//     fn mask_mem(offsets: &ConstantOffsets, mask: &mut [u8]) {
//         //  这个条件语句检查 ConstantOffsets 结构体中是否包含位移信息。如果包含位移信息,说明汇编指令中有位移部分需要被处理
//         if offsets.has_displacement() {
//             // 这行代码从 ConstantOffsets 结构体中获取位移的偏移量(offset)。偏移量表示位移在掩码中的起始位置
//             let off = offsets.displacement_offset();
//             // 这行代码获取位移的大小(size)。大小表示位移在掩码中占用的字节数。
//             let size = offsets.displacement_size();
//             // 遍历掩码数组中的每个字节。enumerate() 方法用于同时获取字节的索引 i 和字节的可变引用 b
//             for (i, b) in mask.iter_mut().enumerate() {
//                 // 检查当前字节的索引 i 是否在位移范围内。如果是的话,将当前字节的值设置为 0,表示该字节的位是无效的
//                 if i >= off && i < off + size {
//                     *b = 0;
//                 }
//             }
//         }
//     }
//
//     fn mask_branch(offsets: &ConstantOffsets, mask: &mut [u8], unmasked_branch_size: usize) {
//         // 检查位移信息中是否包含立即数
//         if offsets.has_immediate() {
//             let off = offsets.immediate_offset(); // 获取立即数的偏移量
//             let size = offsets.immediate_size();   // 获取立即数的大小
//
//             // 如果立即数的大小大于未经掩码的分支部分大小
//             if size > unmasked_branch_size {
//                 // 遍历掩码数组中的每个字节
//                 for (i, b) in mask.iter_mut().enumerate() {
//                     // 如果当前字节的索引位于立即数范围内,则将该字节的值设置为 0,表示无效
//                     if i >= off && i < off + size {
//                         *b = 0;
//                     }
//                 }
//             }
//         }
//     }
//
// }
//
// #[derive(Default)]
// pub struct Sigmaker {}
//
// impl Sigmaker {
//     // 从可执行代码段, 得到指定全局变量
//     pub fn find_sigs(process: &mut Win32Process<impl VirtualMemory>, disasm: &DisAsm, target_global_addr:Address) -> Result<Vec<String>> {
//         // 得到指定 全局变量:ip列表 的映射
//         let ip_addrs = disasm
//             .inverse_map
//             .get(&target_global_addr)
//             .ok_or(Error::Other("没有找到ip列表"))?;
//
//         // 寻找全局变量所在的模块
//         let module = process
//             .module_list()?
//             .iter()
//             .find(|x| x.base <= target_global_addr && target_global_addr < x.base + x.size)
//             .ok_or(Error::Other("没有找到模块"))?
//             .clone();
//
//         // 读取模块头
//         let mut image_buffer = vec![0; size::kb(128)];
//
//         // 读取模块的标头的字节数据
//         process.virt_mem.virt_read_raw_into(module.base, &mut image_buffer).data_part()?;
//
//         // 解析为模块头
//         let pefile = PeFile::from_bytes(&image_buffer).expect("pe头解析失败");
//
//         // 找到所有段在内存中的位置, 和大小
//         let mut ranges = Vec::new();  // 保存了段在模块中的位置, 和段的大小
//         for section in pefile.section_headers().iter() {
//             // 过滤掉不符合的一些特征的段, 然后扫描整个段内容
//             if section.Characteristics & 0x20 != 0 {
//                 ranges.push((Address::from(module.base+(section.VirtualAddress as usize)), section.VirtualSize as usize));
//             }
//         }
//
//         // 存放了 好多buffer的列表, 保存了每个 ip 对应的 128字节的内存数据, 一共 ip_addrs.len() 个 128字节数据
//         // 这些数据有对全局变量操作相关的特征
//         let mut bufs = ip_addrs
//             .iter()
//             .map(|a| (*a, [0; MAX_SIG_LEN]))
//             .collect::<Vec<(Address, [u8; MAX_SIG_LEN])>>();
//
//         // 保存了 ip_addrs 中每个ip 后的128字节数据
//         let mut read_list_info:Vec<_> = bufs
//             .iter_mut()
//             .map(|(addr, buf)| VirtualReadData(*addr, buf))
//             .collect();
//
//         // 一次读取全部的 ip_addrs 中的每个ip后的128字节数据, 通过引用读取到 bufs中了
//         process.virt_mem.virt_read_raw_list(&mut read_list_info).data_part()?;
//
//         let bitness = process.proc_info.proc_arch.bits().into();
//         let mut states = bufs
//             .iter()
//             .map(|(start_ip, buf)| {
//                 let mut decoder = Decoder::new(bitness, buf, DecoderOptions::NONE);
//                 decoder.set_ip(start_ip.as_u64());  // 设置解码器的初始地址, 这个初始地址是相较于程序的绝对地址
//                 SigState {
//                     start_ip: *start_ip,
//                     buf,
//                     decoder,
//                     instrs: Vec::new(),
//                     mask:Vec::new()
//                 }
//             })
//             .collect::<Vec<_>>();
//
//         let mut out = vec![];
//         loop {
//             let mut added = false;
//             for s in states.iter_mut() {
//                 if s.add_single_instr() {
//                     added = true;
//                 }
//             }
//
//             if !added || Self::has_unique_matches(&states, &mut process.virt_mem, &ranges, &mut out)? {
//                 break;
//             }
//
//         }
//         Ok(out)
//     }
//
//     fn has_unique_matches( states: &[SigState], virt_mem: &mut impl VirtualMemory, ranges: &[(Address, usize)], out: &mut Vec<String>) -> Result<bool>{
//         let mut sigs: Vec<_> = states
//             .iter()
//             .map(|s| (s.start_ip, s.buf, &s.mask, 0))
//             .collect();
//
//         // 找到所有段在内存中的位置, 和大小
//         let mut buffer = vec![0; size::kb(64) + MAX_SIG_LEN - 1];
//
//         // 循环 读取 段内的内存, 每次读取64k
//         for (addr, size) in ranges.iter() {
//             // 读取成功, 现在应该在64k的空间内继续查找
//             for off in (0..*size).step_by(size::kb(64)) {
//                 let addr = *addr + off;  // 地址应该是 段基础地址 + 当前段内读取的64k偏移
//                 virt_mem.virt_read_raw_into(addr, &mut buffer).data_part()?;
//
//                 // 滚动64k, 每次读128字节
//                 for (off, w) in buffer.windows(MAX_SIG_LEN).enumerate() {
//                     let addr = addr + off;
//                     for (start_ip, bytes, mask, dup_matches) in sigs.iter_mut() {
//                         let win_iter = w.iter().zip(mask.iter()).map(|(&w, &m)| w & m);
//                         let bytes_iter = bytes.iter().zip(mask.iter()).map(|(&w, &m)| w & m);
//                         if win_iter.eq(bytes_iter) && addr != *start_ip {
//                             *dup_matches += 1;
//                         }
//                     }
//                 }
//
//             }
//         }
//         let mut has_unique = false;
//
//         for (_, buf, mask, dup_matches) in sigs {
//             if dup_matches == 0 {
//                 has_unique = true;
//                 out.push(Self::bytes_to_string(buf, mask));
//             }
//         }
//
//         Ok(has_unique)
//     }
//
//     fn bytes_to_string(bytes: &[u8], mask: &[u8]) -> String {
//         // 使用 zip 方法将字节数组和掩码数组中的对应字节配对
//         // 对每个配对进行映射操作
//         let result: Vec<String> = bytes
//             .iter()
//             .zip(mask.iter())
//             .map(|(&b, &m)| {
//                 // 如果掩码为 0,则将该字节替换为 "?"
//                 // 否则,使用格式化字符串将字节转换为十六进制表示
//                 if m == 0 {
//                     "?".to_string()
//                 } else {
//                     format!("{:02X}", b)
//                 }
//             })
//             .collect(); // 将映射结果收集到一个字符串向量中
//
//         // 使用 join 方法将字符串向量中的元素用空格连接成一个单独的字符串
//         result.join(" ")
//     }
//
// }



use memflow::mem::{VirtualMemory, VirtualReadData};
use memflow::types::{size, Address};
use memflow_win32::error::*;
use memflow_win32::win32::Win32Process;

use iced_x86::{Code, ConstantOffsets, Decoder, DecoderOptions, Instruction, OpKind, Register};
use pelite::PeFile;
use crate::ch_3_disasm::DisAsm;

const MAX_SIG_LENGTH: usize = 128;

struct Sigstate<'a> {
    start_ip: Address,
    buf: &'a [u8; MAX_SIG_LENGTH],
    decoder: Decoder<'a>,
    instrs: Vec<(Instruction, ConstantOffsets)>,
    mask: Vec<u8>,
}

impl Sigstate<'_> {
    fn add_single_instr(&mut self) -> bool {
        if !self.decoder.can_decode() {
            return false;
        }

        let instr = self.decoder.decode();

        if instr.code() == Code::INVALID {
            false
        } else {
            let constant_offsets = self.decoder.get_constant_offsets(&instr);
            self.mask.extend((0..instr.len()).map(|_| 0xff));
            let mask_len = self.mask.len();
            let instr_mask = &mut self.mask[(mask_len - instr.len())..];
            Self::mask_instr(&instr, &constant_offsets, instr_mask);
            self.instrs.push((instr, constant_offsets));
            true
        }
    }

    fn mask_instr(instr: &Instruction, offsets: &ConstantOffsets, mask: &mut [u8]) {
        if let Register::EIP
        | Register::RIP
        | Register::ES
        | Register::CS
        | Register::SS
        | Register::DS
        | Register::FS
        | Register::GS
        | Register::None = instr.memory_base()
        {
            Self::mask_mem(offsets, mask);
        }

        if let Ok(OpKind::NearBranch16)
        | Ok(OpKind::NearBranch32)
        | Ok(OpKind::NearBranch64)
        | Ok(OpKind::FarBranch16)
        | Ok(OpKind::FarBranch32) = instr.try_op_kind(0)
        {
            Self::mask_branch(&offsets, mask, 1);
        }
    }

    fn mask_branch(offsets: &ConstantOffsets, mask: &mut [u8], unmasked_branch_size: usize) {
        if offsets.has_immediate() {
            let off = offsets.immediate_offset();
            let size = offsets.immediate_size();
            if size > unmasked_branch_size {
                for (i, b) in mask.iter_mut().enumerate() {
                    if i >= off && i < off + size {
                        *b = 0;
                    }
                }
            }
        }
    }

    fn mask_mem(offsets: &ConstantOffsets, mask: &mut [u8]) {
        if offsets.has_displacement() {
            let off = offsets.displacement_offset();
            let size = offsets.displacement_size();
            for (i, b) in mask.iter_mut().enumerate() {
                if i >= off && i < off + size {
                    *b = 0;
                }
            }
        }
    }
}

#[derive(Default)]
pub struct Sigmaker {}

impl Sigmaker {
    fn has_unique_matches(
        states: &[Sigstate],
        virt_mem: &mut impl VirtualMemory,
        ranges: &[(Address, usize)],
        out: &mut Vec<String>,
    ) -> Result<bool> {
        let mut sigs: Vec<_> = states
            .iter()
            .map(|s| (s.start_ip, s.buf, &s.mask, 0))
            .collect();

        const CHUNK_SIZE: usize = size::kb(4);
        let mut buf = vec![0; CHUNK_SIZE + MAX_SIG_LENGTH - 1];

        for &(addr, size) in ranges {
            for off in (0..size).step_by(CHUNK_SIZE) {
                let addr = addr + off;
                virt_mem
                    .virt_read_raw_into(addr, buf.as_mut_slice())
                    .data_part()?;

                for (off, w) in buf.windows(MAX_SIG_LENGTH).enumerate() {
                    let addr = addr + off;
                    for (start_ip, bytes, mask, dup_matches) in sigs.iter_mut() {
                        let win_iter = w.iter().zip(mask.iter()).map(|(&w, &m)| w & m);
                        let bytes_iter = bytes.iter().zip(mask.iter()).map(|(&w, &m)| w & m);
                        if win_iter.eq(bytes_iter) && addr != *start_ip {
                            *dup_matches += 1;
                        }
                    }
                }
            }
        }

        let mut has_unique = false;

        for (_, buf, mask, dup_matches) in sigs {
            if dup_matches == 0 {
                has_unique = true;
                out.push(Self::bytes_to_string(buf, mask));
            }
        }

        Ok(has_unique)
    }

    fn bytes_to_string(bytes: &[u8], mask: &[u8]) -> String {
        bytes
            .iter()
            .zip(mask.iter())
            .map(|(&b, &m)| {
                if m == 0 {
                    "?".to_string()
                } else {
                    format!("{:02X}", b)
                }
            })
            .collect::<Vec<_>>()
            .join(" ")
    }

    pub fn find_sigs(
        process: &mut Win32Process<impl VirtualMemory>,
        disasm: &DisAsm,
        target_global: Address,
    ) -> Result<Vec<String>> {
        let addrs = disasm
            .inverse_map
            .get(&target_global)
            .ok_or(Error::Other("Invalid global variable"))?;

        let module = process
            .module_list()?
            .into_iter()
            .find(|m| m.base <= target_global && m.base + m.size > target_global)
            .ok_or(Error::Other("Could not find target module"))?;

        let mut image = vec![0; size::kb(128)];

        process
            .virt_mem
            .virt_read_raw_into(module.base, &mut image)
            .data_part()?;

        let pefile =
            PeFile::from_bytes(&image).map_err(|_| Error::Other("Failed to parse header"))?;

        const IMAGE_SCN_CNT_CODE: u32 = 0x20;

        let ranges: Vec<(Address, usize)> = pefile
            .section_headers()
            .iter()
            .filter(|s| (s.Characteristics & IMAGE_SCN_CNT_CODE) != 0)
            .map(|s| {
                (
                    module.base + s.VirtualAddress as usize,
                    s.VirtualSize as usize,
                )
            })
            .collect();

        let mut bufs: Vec<(Address, [u8; MAX_SIG_LENGTH])> =
            addrs.iter().map(|&a| (a, [0; MAX_SIG_LENGTH])).collect();

        let mut read_list: Vec<_> = bufs
            .iter_mut()
            .map(|(a, b)| VirtualReadData(*a, b))
            .collect();

        process
            .virt_mem
            .virt_read_raw_list(&mut read_list)
            .data_part()?;

        let bitness = process.proc_info.proc_arch.bits().into();

        let mut states: Vec<_> = bufs
            .iter()
            .map(|(start_ip, buf)| {
                let mut decoder = Decoder::new(bitness, buf, DecoderOptions::NONE);
                decoder.set_ip(start_ip.as_u64());
                Sigstate {
                    start_ip: *start_ip,
                    buf,
                    decoder,
                    instrs: vec![],
                    mask: vec![],
                }
            })
            .collect();

        let mut out = vec![];

        loop {
            let mut added = false;
            for s in states.iter_mut() {
                if s.add_single_instr() {
                    added = true;
                }
            }
            if !added
                || Self::has_unique_matches(&states, &mut process.virt_mem, &ranges, &mut out)?
            {
                break;
            }
        }

        Ok(out)
    }
}

scanner

use std::io::Read;
use memflow::{Address, PartialResultExt, size, VirtualMemory};


// 一个扫描仪
#[derive(Default)]
pub struct ValueScanner {
    pub matches: Vec<Address>,  // 存放了 符合 data 数据的内存地址
    // mem_maps: Vec<(Address, usize)>
}

impl ValueScanner{
    pub fn reset(&mut self) -> &mut Self {
        self.matches.clear();
        // self.mem_maps.clear();
        self
    }
    pub fn scan<T: VirtualMemory>(&mut self, virt_mem: &mut T, data: &[u8]) -> &mut Self{
        if self.matches.is_empty() {
            let mut buffer = vec![0; size::kb(64) + data.len() - 1];
            // 合并低范围的内存, 限定合并空间, 减少将来需要扫描的范围
            let mut mem_maps = virt_mem.virt_page_map_range(size::mb(16), Address::NULL, (1_usize << 47).into());

            // 循环所有的内存块
            for (block_addr, block_size) in mem_maps.iter(){
                // 循环 读取块内内存, 每次读取64k
                for offset in (0..*block_size).step_by(size::kb(64)) {
                    if let Ok(_) = virt_mem.virt_read_raw_into(*block_addr + offset, &mut buffer).data_part() {
                        // 读取成功, 现在应该在64k的空间内继续查找
                        for (o, buf) in buffer.windows(data.len()).enumerate() {
                            if buf == data {
                                let addr = *block_addr + offset + o;
                                self.matches.push(addr);
                            }
                        }
                    }
                }
            }
        } else {
            let mut new_matches = vec![];
            // 从已有扫描出来的继续扫描
            let mut buffer = vec![0; data.len()];
            for addr in self.matches.iter() {
                virt_mem.virt_read_raw_into(*addr, &mut buffer).data_part().unwrap();
                if &buffer == data {
                    new_matches.push(*addr)
                }
            }
            self.matches = new_matches;
        }
        self
    }

    // 返回一个匹配规则迭代器
    pub fn matches_iter(&self) -> &Vec<Address> {
        &self.matches
    }

    // 循环所有匹配的地址, 打印
    pub fn print_matches<T: VirtualMemory>(&self,  virt_mem: &mut T, buf_len:usize, type_name: &str) {
        // let buf = Vec::new();
        for addr in self.matches.iter(){
            let buf = virt_mem.virt_read_raw(*addr, buf_len).data_part().unwrap();
            match type_name {
                "i64" => {
                    let value = i64::from_ne_bytes(buf.try_into().unwrap());
                    println!("addr: {addr}, value: {value}")
                }
                "u64" => {
                    let value = u64::from_ne_bytes(buf.try_into().unwrap());
                    println!("addr: {addr}, value: {value}")
                }
                "i32" => {
                    let value = i32::from_ne_bytes(buf.try_into().unwrap());
                    println!("addr: {addr}, value: {value}")
                }
                "u32" => {
                    let value = u32::from_ne_bytes(buf.try_into().unwrap());
                    println!("addr: {addr}, value: {value}")
                }
                "i16" => {
                    let value = i16::from_ne_bytes(buf.try_into().unwrap());
                    println!("addr: {addr}, value: {value}")
                }
                "u16" => {
                    let value = u16::from_ne_bytes(buf.try_into().unwrap());
                    println!("addr: {addr}, value: {value}")
                }
                "i8" => {
                    let value = i8::from_ne_bytes(buf.try_into().unwrap());
                    println!("addr: {addr}, value: {value}")
                }
                "u8" => {
                    let value = u8::from_ne_bytes(buf.try_into().unwrap());
                    println!("addr: {addr}, value: {value}")
                }
                "f64" => {
                    let value = f64::from_ne_bytes(buf.try_into().unwrap());
                    println!("addr: {addr}, value: {value}")
                }
                "f32" => {
                    let value = f32::from_ne_bytes(buf.try_into().unwrap());
                    println!("addr: {addr}, value: {value}")
                }
                "str" => {
                    println!("ddr: {addr}, {}", String::from_utf8_lossy(&buf));
                }
                "str_utf16" => {
                    let mut v = vec![];

                    for w in buf.chunks_exact(2) {
                        let u = u16::from_ne_bytes(w.try_into().unwrap());
                        v.push(u);
                    }
                    let s = String::from_utf16_lossy(&v);
                    println!("addr: {addr}, value: {s}")
                }
                _ => {
                    println!("无效的类型: {}", type_name);
                }
            }
        }
    }


}