mirror of https://github.com/jackwener/wx-cli.git
Merge 42169de2f0 into 08af894594
commit
3696d6d97d
|
|
@ -200,11 +200,6 @@ impl DbCache {
|
|||
}
|
||||
|
||||
pub async fn get_with_mode(&self, rel_key: &str) -> Result<Option<CacheResolve>> {
|
||||
let enc_key_hex = match self.all_keys.get(rel_key) {
|
||||
Some(k) => k.clone(),
|
||||
None => return Ok(None),
|
||||
};
|
||||
|
||||
let db_path = self.db_dir.join(
|
||||
rel_key
|
||||
.replace('\\', std::path::MAIN_SEPARATOR_STR)
|
||||
|
|
@ -214,6 +209,21 @@ impl DbCache {
|
|||
return Ok(None);
|
||||
}
|
||||
|
||||
let enc_key_hex = match self.all_keys.get(rel_key) {
|
||||
Some(k) => k.clone(),
|
||||
None => {
|
||||
// Fallback: look up by DB salt for keys saved as "_by_salt/<salt>"
|
||||
// when the DB file wasn't accessible during `wx init`.
|
||||
let salt = crate::scanner::read_db_salt(&db_path);
|
||||
match salt.and_then(|s| {
|
||||
self.all_keys.get(&format!("_by_salt/{}", s)).cloned()
|
||||
}) {
|
||||
Some(k) => k,
|
||||
None => return Ok(None),
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let wal_path = wal_path_for(&db_path);
|
||||
let db_mt = mtime_nanos(&db_path);
|
||||
let wal_mt = if wal_path.exists() {
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
/// 通过 /proc/<pid>/mem 读取内存内容,
|
||||
/// 搜索 x'<64hex><32hex>' 格式的 SQLCipher 密钥
|
||||
use anyhow::{Context, Result};
|
||||
use std::collections::HashMap;
|
||||
use std::io::{Read, Seek, SeekFrom};
|
||||
use std::path::Path;
|
||||
|
||||
|
|
@ -89,21 +90,33 @@ pub fn scan_keys(db_dir: &Path) -> Result<Vec<KeyEntry>> {
|
|||
}
|
||||
eprintln!("找到 {} 个候选密钥", raw_keys.len());
|
||||
|
||||
// 无法匹配 DB 文件的密钥用 _by_salt/<salt> 保存,daemon 会做 salt 回退查找,
|
||||
// 确保所有在内存中找到的密钥都不会因 DB 文件权限或路径问题而丢失。
|
||||
let db_salt_map: HashMap<&str, &str> = db_salts
|
||||
.iter()
|
||||
.map(|(salt, name)| (salt.as_str(), name.as_str()))
|
||||
.collect();
|
||||
|
||||
let mut entries = Vec::new();
|
||||
for (key_hex, salt_hex) in &raw_keys {
|
||||
for (db_salt, db_name) in &db_salts {
|
||||
if salt_hex == db_salt {
|
||||
entries.push(KeyEntry {
|
||||
db_name: db_name.clone(),
|
||||
enc_key: key_hex.clone(),
|
||||
salt: salt_hex.clone(),
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
let db_name = db_salt_map
|
||||
.get(salt_hex.as_str())
|
||||
.map(|s| s.to_string())
|
||||
.unwrap_or_else(|| format!("_by_salt/{}", salt_hex));
|
||||
entries.push(KeyEntry {
|
||||
db_name,
|
||||
enc_key: key_hex.clone(),
|
||||
salt: salt_hex.clone(),
|
||||
});
|
||||
}
|
||||
|
||||
eprintln!("匹配到 {}/{} 个密钥", entries.len(), raw_keys.len());
|
||||
let matched = entries.iter().filter(|e| !e.db_name.starts_with("_by_salt/")).count();
|
||||
eprintln!(
|
||||
"匹配到 {}/{} 个密钥(另有 {} 个按 salt 保存)",
|
||||
matched,
|
||||
raw_keys.len(),
|
||||
entries.len() - matched
|
||||
);
|
||||
Ok(entries)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
/// 2. WeChat 需要进行 ad-hoc 签名
|
||||
/// 3. 在内存中搜索 x'<64hex><32hex>' 格式的 SQLCipher 密钥
|
||||
use anyhow::{bail, Context, Result};
|
||||
use std::collections::HashMap;
|
||||
use std::path::Path;
|
||||
|
||||
use super::{collect_db_salts, KeyEntry};
|
||||
|
|
@ -141,22 +142,33 @@ pub fn scan_keys(db_dir: &Path) -> Result<Vec<KeyEntry>> {
|
|||
let raw_keys = scan_memory(task)?;
|
||||
eprintln!("找到 {} 个候选密钥", raw_keys.len());
|
||||
|
||||
// 5. 将密钥与数据库 salt 匹配
|
||||
// 5. 将密钥与数据库 salt 匹配,无法匹配的用 _by_salt/<salt> 保存,
|
||||
// 确保所有在内存中找到的密钥都不会因 DB 文件权限或路径问题而丢失。
|
||||
let db_salt_map: HashMap<&str, &str> = db_salts
|
||||
.iter()
|
||||
.map(|(salt, name)| (salt.as_str(), name.as_str()))
|
||||
.collect();
|
||||
|
||||
let mut entries = Vec::new();
|
||||
for (key_hex, salt_hex) in &raw_keys {
|
||||
for (db_salt, db_name) in &db_salts {
|
||||
if salt_hex == db_salt {
|
||||
entries.push(KeyEntry {
|
||||
db_name: db_name.clone(),
|
||||
enc_key: key_hex.clone(),
|
||||
salt: salt_hex.clone(),
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
let db_name = db_salt_map
|
||||
.get(salt_hex.as_str())
|
||||
.map(|s| s.to_string())
|
||||
.unwrap_or_else(|| format!("_by_salt/{}", salt_hex));
|
||||
entries.push(KeyEntry {
|
||||
db_name,
|
||||
enc_key: key_hex.clone(),
|
||||
salt: salt_hex.clone(),
|
||||
});
|
||||
}
|
||||
|
||||
eprintln!("匹配到 {}/{} 个密钥", entries.len(), raw_keys.len());
|
||||
let matched = entries.iter().filter(|e| !e.db_name.starts_with("_by_salt/")).count();
|
||||
eprintln!(
|
||||
"匹配到 {}/{} 个密钥(另有 {} 个按 salt 保存)",
|
||||
matched,
|
||||
raw_keys.len(),
|
||||
entries.len() - matched
|
||||
);
|
||||
Ok(entries)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
/// - VirtualQueryEx: 枚举内存区域
|
||||
/// - ReadProcessMemory: 读取内存内容
|
||||
use anyhow::{Context, Result};
|
||||
use std::collections::HashMap;
|
||||
use std::path::Path;
|
||||
use windows::Win32::Foundation::{CloseHandle, HANDLE};
|
||||
use windows::Win32::System::Diagnostics::Debug::ReadProcessMemory;
|
||||
|
|
@ -79,20 +80,33 @@ pub fn scan_keys(db_dir: &Path) -> Result<Vec<KeyEntry>> {
|
|||
let _ = CloseHandle(process);
|
||||
}
|
||||
|
||||
// 无法匹配 DB 文件的密钥用 _by_salt/<salt> 保存,daemon 会做 salt 回退查找,
|
||||
// 确保所有在内存中找到的密钥都不会因 DB 文件权限或路径问题而丢失。
|
||||
let db_salt_map: HashMap<&str, &str> = db_salts
|
||||
.iter()
|
||||
.map(|(salt, name)| (salt.as_str(), name.as_str()))
|
||||
.collect();
|
||||
|
||||
let mut entries = Vec::new();
|
||||
for (key_hex, salt_hex) in &raw_keys {
|
||||
for (db_salt, db_name) in &db_salts {
|
||||
if salt_hex == db_salt {
|
||||
entries.push(KeyEntry {
|
||||
db_name: db_name.clone(),
|
||||
enc_key: key_hex.clone(),
|
||||
salt: salt_hex.clone(),
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
let db_name = db_salt_map
|
||||
.get(salt_hex.as_str())
|
||||
.map(|s| s.to_string())
|
||||
.unwrap_or_else(|| format!("_by_salt/{}", salt_hex));
|
||||
entries.push(KeyEntry {
|
||||
db_name,
|
||||
enc_key: key_hex.clone(),
|
||||
salt: salt_hex.clone(),
|
||||
});
|
||||
}
|
||||
eprintln!("匹配到 {}/{} 个密钥", entries.len(), raw_keys.len());
|
||||
|
||||
let matched = entries.iter().filter(|e| !e.db_name.starts_with("_by_salt/")).count();
|
||||
eprintln!(
|
||||
"匹配到 {}/{} 个密钥(另有 {} 个按 salt 保存)",
|
||||
matched,
|
||||
raw_keys.len(),
|
||||
entries.len() - matched
|
||||
);
|
||||
Ok(entries)
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue