115 lines
3.8 KiB
Rust
115 lines
3.8 KiB
Rust
use anyhow::Context;
|
|
use regex::bytes::Regex;
|
|
use sha2::Digest;
|
|
use std::{fs::File, io::Read, path::PathBuf};
|
|
|
|
#[cfg(any(target_os = "linux", target_os = "macos"))]
|
|
fn get_steam_root() -> anyhow::Result<PathBuf> {
|
|
let mut base = dirs::home_dir().with_context(|| "Couldn't figure out your home directory")?;
|
|
|
|
#[cfg(target_os="linux")]
|
|
base.push(".steam/root");
|
|
|
|
#[cfg(target_os="macos")]
|
|
base.push("Library/Application Support/Steam");
|
|
|
|
Ok(base)
|
|
}
|
|
|
|
#[cfg(target_os = "windows")]
|
|
fn get_steam_root() -> anyhow::Result<PathBuf> {
|
|
use registry::{self, Security, Data};
|
|
|
|
let key = registry::Hive::LocalMachine.open(r"SOFTWARE\Wow6432Node\Valve\Steam", Security::Read)?;
|
|
let value = match key.value("InstallPath")? {
|
|
Data::String(s) => Some(s.to_string_lossy()),
|
|
Data::ExpandString(s) => Some(s.to_string_lossy()),
|
|
_ => None
|
|
}.with_context(|| "Couldn't read the steam install path from registry")?;
|
|
|
|
let mut base = PathBuf::from(value);
|
|
|
|
Ok(base)
|
|
}
|
|
|
|
pub fn get_omori_path() -> anyhow::Result<PathBuf> {
|
|
let mut base = get_steam_root()?;
|
|
|
|
base.push("steamapps/libraryfolders.vdf");
|
|
|
|
let mut buffer = Vec::new();
|
|
|
|
let mut fd = File::open(base)?;
|
|
fd.read_to_end(&mut buffer)?;
|
|
|
|
let data = String::from_utf8(buffer)?;
|
|
let data = keyvalues_parser::Vdf::parse(&data.as_str())?;
|
|
let data = data.value.get_obj().with_context(|| "Couldn't get the steam library libraryfolders object.")?;
|
|
let keys = data.keys();
|
|
|
|
let mut omori_path: Option<PathBuf> = None;
|
|
for key in keys {
|
|
println!("{:?}", key);
|
|
let entry = data.get(key).with_context(|| "Couldn't read specific steam library libraryfolders object.")?;
|
|
let entry = entry.get(0).with_context(|| "Couldn't read specific steam library libraryfolders object.")?;
|
|
let entry = entry.get_obj().with_context(|| "libraryfolders parsing failed: Not an object")?;
|
|
|
|
let apps = entry.get("apps").with_context(|| "libraryfolders parsing failed: No apps")?;
|
|
let apps = apps.get(0).with_context(|| "libraryfolders parsing failed: No apps")?;
|
|
let apps = apps.get_obj().with_context(|| "libraryfolders parsing failed: No apps")?;
|
|
let apps: Vec<_> = apps.keys().collect();
|
|
|
|
let path = entry.get("path").with_context(|| "libraryfolders parsing failed: No path")?;
|
|
let path = path.get(0).with_context(|| "libraryfolders parsing failed: No path")?;
|
|
let path = path.get_str().with_context(|| "libraryfolders parsing failed: No path")?;
|
|
|
|
if apps.iter().find(|x| (**x).eq("1150690")).is_some() {
|
|
let mut base = PathBuf::from(path);
|
|
|
|
#[cfg(not(target_os = "macos"))]
|
|
base.push("steamapps/common/OMORI/www");
|
|
|
|
#[cfg(target_os = "macos")]
|
|
base.push("steamapps/common/OMORI/OMORI.app/Contents/Resources/app.nw");
|
|
|
|
omori_path = Some(base);
|
|
}
|
|
}
|
|
|
|
|
|
omori_path.with_context(|| "Failed to find omori")
|
|
}
|
|
|
|
const GAME_KEY_HASH: &[u8; 32] = include_bytes!("keyhash");
|
|
|
|
pub fn get_omori_key() -> anyhow::Result<Vec<u8>> {
|
|
let mut base: PathBuf = get_steam_root()?;
|
|
|
|
base.push("appcache/appinfo.vdf");
|
|
|
|
let mut buffer = Vec::new();
|
|
|
|
let mut fd = File::open(base)?;
|
|
fd.read_to_end(&mut buffer)?;
|
|
drop(fd);
|
|
|
|
let re = Regex::new(r"--([0-9a-f]{32})")?;
|
|
|
|
for (_, [key]) in re.captures_iter(&buffer).map(|c| c.extract()) {
|
|
let hash = sha2::Sha256::digest(key);
|
|
|
|
let mut equal = true;
|
|
for i in 0..32 {
|
|
if hash[i] != GAME_KEY_HASH[i] {
|
|
equal = false;
|
|
}
|
|
}
|
|
|
|
if equal {
|
|
return Ok(key.to_vec())
|
|
}
|
|
}
|
|
|
|
|
|
Err(anyhow::anyhow!("Couldn't find any valid decryption key for OMORI in your Steam installation."))
|
|
} |