forked from reversedrooms/hk4e-patch
First push
This commit is contained in:
parent
151d3da8ac
commit
7898141000
14 changed files with 590 additions and 0 deletions
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
/target
|
||||||
|
Cargo.lock
|
31
Cargo.toml
Normal file
31
Cargo.toml
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
[package]
|
||||||
|
name = "hk4e-patch"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
name = "version"
|
||||||
|
crate-type = ["cdylib"]
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
anyhow = "1.0.81"
|
||||||
|
ilhook = "2.1.0"
|
||||||
|
lazy_static = "1.4.0"
|
||||||
|
libloading = "0.8.3"
|
||||||
|
windows = { version = "0.54.0", features = [
|
||||||
|
"Win32_Foundation",
|
||||||
|
"Win32_System_SystemServices",
|
||||||
|
"Win32_System_LibraryLoader",
|
||||||
|
"Win32_System_Console",
|
||||||
|
"Win32_System_Threading",
|
||||||
|
"Win32_System_Memory",
|
||||||
|
] }
|
||||||
|
|
||||||
|
[build-dependencies]
|
||||||
|
cc = "1.0.90"
|
||||||
|
|
||||||
|
[profile.release]
|
||||||
|
strip = true # Automatically strip symbols from the binary.
|
||||||
|
lto = true # Link-time optimization.
|
||||||
|
opt-level = 3 # Optimization level 3.
|
||||||
|
codegen-units = 1 # Maximum size reduction optimizations.
|
11
build.rs
Normal file
11
build.rs
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
fn main() {
|
||||||
|
cc::Build::new().file("version.asm").compile("version");
|
||||||
|
|
||||||
|
println!("cargo:rerun-if-changed=version.asm");
|
||||||
|
println!(
|
||||||
|
"cargo:rustc-link-search=native={}",
|
||||||
|
std::env::var("OUT_DIR").unwrap()
|
||||||
|
);
|
||||||
|
println!("cargo:rustc-link-lib=static=version");
|
||||||
|
println!("cargo:rustc-link-arg=/DEF:version.def");
|
||||||
|
}
|
BIN
server_public_key.bin
Normal file
BIN
server_public_key.bin
Normal file
Binary file not shown.
48
src/interceptor.rs
Normal file
48
src/interceptor.rs
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
use anyhow::{bail, Result};
|
||||||
|
use ilhook::x64::{
|
||||||
|
CallbackOption, HookFlags, HookPoint, HookType, Hooker, JmpBackRoutine, RetnRoutine,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct Interceptor {
|
||||||
|
pub hooks: Vec<HookPoint>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Interceptor {
|
||||||
|
pub const fn new() -> Self {
|
||||||
|
Self { hooks: Vec::new() }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn attach(&mut self, addr: usize, routine: JmpBackRoutine) -> Result<()> {
|
||||||
|
let hooker = Hooker::new(
|
||||||
|
addr,
|
||||||
|
HookType::JmpBack(routine),
|
||||||
|
CallbackOption::None,
|
||||||
|
0,
|
||||||
|
HookFlags::empty(),
|
||||||
|
);
|
||||||
|
|
||||||
|
let Ok(hook_point) = hooker.hook() else {
|
||||||
|
bail!("Failed to attach 0x{addr:X}")
|
||||||
|
};
|
||||||
|
|
||||||
|
self.hooks.push(hook_point);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn replace(&mut self, addr: usize, routine: RetnRoutine) -> Result<()> {
|
||||||
|
let hooker = Hooker::new(
|
||||||
|
addr,
|
||||||
|
HookType::Retn(routine),
|
||||||
|
CallbackOption::None,
|
||||||
|
0,
|
||||||
|
HookFlags::empty(),
|
||||||
|
);
|
||||||
|
|
||||||
|
let Ok(hook_point) = hooker.hook() else {
|
||||||
|
bail!("Failed to replace 0x{addr:X}")
|
||||||
|
};
|
||||||
|
|
||||||
|
self.hooks.push(hook_point);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
61
src/lib.rs
Normal file
61
src/lib.rs
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
#![feature(str_from_utf16_endian)]
|
||||||
|
|
||||||
|
use std::{sync::RwLock, time::Duration};
|
||||||
|
|
||||||
|
use lazy_static::lazy_static;
|
||||||
|
use util::try_get_base_address;
|
||||||
|
use windows::Win32::Foundation::HINSTANCE;
|
||||||
|
use windows::Win32::System::Console;
|
||||||
|
use windows::Win32::System::SystemServices::DLL_PROCESS_ATTACH;
|
||||||
|
|
||||||
|
mod interceptor;
|
||||||
|
mod marshal;
|
||||||
|
mod modules;
|
||||||
|
mod util;
|
||||||
|
mod version;
|
||||||
|
use version::VersionDllProxy;
|
||||||
|
|
||||||
|
use crate::modules::{Http, MhyContext, ModuleManager, Security};
|
||||||
|
|
||||||
|
unsafe fn thread_func() {
|
||||||
|
let base = loop {
|
||||||
|
if let Some(base) = try_get_base_address("UserAssembly.dll") {
|
||||||
|
break base;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::thread::sleep(Duration::from_millis(500));
|
||||||
|
};
|
||||||
|
|
||||||
|
std::thread::sleep(Duration::from_secs(7));
|
||||||
|
|
||||||
|
util::disable_memprotect_guard();
|
||||||
|
Console::AllocConsole().unwrap();
|
||||||
|
|
||||||
|
println!("Genshin Impact encryption patch\nMade by xeondev\nTo work with NaviaImpact: git.xeondev.com/reversedrooms/NaviaImpact");
|
||||||
|
println!("UserAssembly: {:X}", base);
|
||||||
|
|
||||||
|
let mut module_manager = MODULE_MANAGER.write().unwrap();
|
||||||
|
module_manager.enable(MhyContext::<Http>::new(base));
|
||||||
|
module_manager.enable(MhyContext::<Security>::new(base));
|
||||||
|
|
||||||
|
println!("Successfully initialized!");
|
||||||
|
}
|
||||||
|
|
||||||
|
lazy_static! {
|
||||||
|
static ref VERSION_DLL_PROXY: version::VersionDllProxy =
|
||||||
|
VersionDllProxy::new().expect("Failed to load version.dll");
|
||||||
|
static ref MODULE_MANAGER: RwLock<ModuleManager> = RwLock::new(ModuleManager::default());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
unsafe extern "system" fn DllMain(_: HINSTANCE, call_reason: u32, _: *mut ()) -> bool {
|
||||||
|
if call_reason == DLL_PROCESS_ATTACH {
|
||||||
|
VERSION_DLL_PROXY
|
||||||
|
.load_functions()
|
||||||
|
.expect("Failed to load functions from version.dll");
|
||||||
|
|
||||||
|
std::thread::spawn(|| thread_func());
|
||||||
|
}
|
||||||
|
|
||||||
|
true
|
||||||
|
}
|
15
src/marshal.rs
Normal file
15
src/marshal.rs
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
use std::ffi::CStr;
|
||||||
|
|
||||||
|
use crate::util;
|
||||||
|
|
||||||
|
const PTR_TO_STRING_ANSI: usize = 0xC61DB80;
|
||||||
|
type MarshalPtrToStringAnsi = unsafe extern "fastcall" fn(*const u8) -> *const u8;
|
||||||
|
|
||||||
|
pub unsafe fn ptr_to_string_ansi(content: &CStr) -> *const u8 {
|
||||||
|
let func = std::mem::transmute::<usize, MarshalPtrToStringAnsi>(base() + PTR_TO_STRING_ANSI);
|
||||||
|
func(content.to_bytes_with_nul().as_ptr())
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn base() -> usize {
|
||||||
|
util::try_get_base_address("UserAssembly.dll").unwrap()
|
||||||
|
}
|
45
src/modules/http.rs
Normal file
45
src/modules/http.rs
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
use std::ffi::CString;
|
||||||
|
|
||||||
|
use super::{MhyContext, MhyModule, ModuleType};
|
||||||
|
use crate::marshal;
|
||||||
|
use anyhow::Result;
|
||||||
|
use ilhook::x64::Registers;
|
||||||
|
|
||||||
|
const UNITY_WEB_REQUEST_SET_URL: usize = 0xCFC7FE0;
|
||||||
|
|
||||||
|
pub struct Http;
|
||||||
|
|
||||||
|
impl MhyModule for MhyContext<Http> {
|
||||||
|
unsafe fn init(&mut self) -> Result<()> {
|
||||||
|
self.interceptor.attach(
|
||||||
|
self.assembly_base + UNITY_WEB_REQUEST_SET_URL,
|
||||||
|
on_uwr_set_url,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn de_init(&mut self) -> Result<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_module_type(&self) -> super::ModuleType {
|
||||||
|
ModuleType::Http
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe extern "win64" fn on_uwr_set_url(reg: *mut Registers, _: usize) {
|
||||||
|
let str_length = *((*reg).rdx.wrapping_add(16) as *const u32);
|
||||||
|
let str_ptr = (*reg).rdx.wrapping_add(20) as *const u8;
|
||||||
|
|
||||||
|
let slice = std::slice::from_raw_parts(str_ptr, (str_length * 2) as usize);
|
||||||
|
let url = String::from_utf16le(slice).unwrap();
|
||||||
|
|
||||||
|
let mut new_url = String::from("http://127.0.0.1:21000");
|
||||||
|
url.split('/').skip(3).for_each(|s| {
|
||||||
|
new_url.push_str("/");
|
||||||
|
new_url.push_str(s);
|
||||||
|
});
|
||||||
|
|
||||||
|
println!("Redirect: {url} -> {new_url}");
|
||||||
|
(*reg).rdx =
|
||||||
|
marshal::ptr_to_string_ansi(CString::new(new_url.as_str()).unwrap().as_c_str()) as u64;
|
||||||
|
}
|
63
src/modules/mod.rs
Normal file
63
src/modules/mod.rs
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use anyhow::Result;
|
||||||
|
|
||||||
|
use crate::interceptor::Interceptor;
|
||||||
|
|
||||||
|
mod http;
|
||||||
|
mod security;
|
||||||
|
|
||||||
|
pub use http::Http;
|
||||||
|
pub use security::Security;
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct ModuleManager {
|
||||||
|
modules: HashMap<ModuleType, Box<dyn MhyModule>>,
|
||||||
|
}
|
||||||
|
unsafe impl Sync for ModuleManager {}
|
||||||
|
unsafe impl Send for ModuleManager {}
|
||||||
|
|
||||||
|
impl ModuleManager {
|
||||||
|
pub unsafe fn enable(&mut self, module: impl MhyModule + 'static) {
|
||||||
|
let mut boxed_module = Box::new(module);
|
||||||
|
boxed_module.init().unwrap();
|
||||||
|
self.modules
|
||||||
|
.insert(boxed_module.get_module_type(), boxed_module);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub unsafe fn disable(&mut self, module_type: ModuleType) {
|
||||||
|
let module = self.modules.remove(&module_type);
|
||||||
|
if let Some(mut module) = module {
|
||||||
|
module.as_mut().de_init().unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Hash, PartialEq, Eq)]
|
||||||
|
pub enum ModuleType {
|
||||||
|
Http,
|
||||||
|
Security,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait MhyModule {
|
||||||
|
unsafe fn init(&mut self) -> Result<()>;
|
||||||
|
unsafe fn de_init(&mut self) -> Result<()>;
|
||||||
|
fn get_module_type(&self) -> ModuleType;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct MhyContext<T> {
|
||||||
|
pub assembly_base: usize,
|
||||||
|
pub interceptor: Interceptor,
|
||||||
|
_phantom: std::marker::PhantomData<T>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> MhyContext<T> {
|
||||||
|
pub const fn new(assembly_base: usize) -> Self {
|
||||||
|
Self {
|
||||||
|
assembly_base,
|
||||||
|
interceptor: Interceptor::new(),
|
||||||
|
_phantom: std::marker::PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
66
src/modules/security.rs
Normal file
66
src/modules/security.rs
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
use super::{MhyContext, MhyModule, ModuleType};
|
||||||
|
use anyhow::Result;
|
||||||
|
use ilhook::x64::Registers;
|
||||||
|
|
||||||
|
const IL2CPP_ARRAY_NEW: usize = 0x5432A0;
|
||||||
|
const KEY_SIGN_CHECK: usize = 0x4235;
|
||||||
|
|
||||||
|
const KEY_SIZE: u64 = 272;
|
||||||
|
const KEY_PREFIX: u64 = 0x0D700010182020A01;
|
||||||
|
static SERVER_PUBLIC_KEY: &[u8] = include_bytes!("../../server_public_key.bin");
|
||||||
|
type Il2cppArrayNew = unsafe extern "fastcall" fn(u64, u64) -> *const u8;
|
||||||
|
|
||||||
|
pub struct Security;
|
||||||
|
|
||||||
|
impl MhyModule for MhyContext<Security> {
|
||||||
|
unsafe fn init(&mut self) -> Result<()> {
|
||||||
|
self.interceptor.replace(
|
||||||
|
self.assembly_base + IL2CPP_ARRAY_NEW,
|
||||||
|
il2cpp_array_new_replacement,
|
||||||
|
)?;
|
||||||
|
self.interceptor
|
||||||
|
.attach(self.assembly_base + KEY_SIGN_CHECK, after_key_sign_check)
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn de_init(&mut self) -> Result<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_module_type(&self) -> super::ModuleType {
|
||||||
|
ModuleType::Security
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sign check of rsa key that we just replaced.
|
||||||
|
unsafe extern "win64" fn after_key_sign_check(reg: *mut Registers, _: usize) {
|
||||||
|
(*reg).rax = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
static mut KEY_PTR: Option<*mut u8> = None;
|
||||||
|
unsafe extern "win64" fn il2cpp_array_new_replacement(
|
||||||
|
reg: *mut Registers,
|
||||||
|
actual_func: usize,
|
||||||
|
_: usize,
|
||||||
|
) -> usize {
|
||||||
|
let il2cpp_array_new = std::mem::transmute::<usize, Il2cppArrayNew>(actual_func);
|
||||||
|
let ret_val = il2cpp_array_new((*reg).rcx, (*reg).rdx) as usize;
|
||||||
|
|
||||||
|
let rdx = (*reg).rdx;
|
||||||
|
if rdx == KEY_SIZE {
|
||||||
|
KEY_PTR = Some(ret_val as *mut u8);
|
||||||
|
} else {
|
||||||
|
if let Some(key_ptr) = KEY_PTR {
|
||||||
|
if *(key_ptr.wrapping_add(32) as *const u64) == KEY_PREFIX {
|
||||||
|
std::ptr::copy_nonoverlapping(
|
||||||
|
SERVER_PUBLIC_KEY.as_ptr(),
|
||||||
|
key_ptr.wrapping_add(32),
|
||||||
|
SERVER_PUBLIC_KEY.len(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
KEY_PTR = None;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret_val
|
||||||
|
}
|
63
src/util.rs
Normal file
63
src/util.rs
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
use core::iter::once;
|
||||||
|
use std::ffi::{c_void, OsStr};
|
||||||
|
|
||||||
|
use std::os::windows::ffi::OsStrExt;
|
||||||
|
use windows::Win32::System::LibraryLoader::{GetProcAddress, GetModuleHandleW};
|
||||||
|
use windows::Win32::System::Memory::{PAGE_EXECUTE_READWRITE, PAGE_PROTECTION_FLAGS, VirtualProtect};
|
||||||
|
use windows::core::{PCSTR, PCWSTR};
|
||||||
|
|
||||||
|
pub fn wide_str(value: &str) -> Vec<u16> {
|
||||||
|
OsStr::new(value).encode_wide().chain(once(0)).collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn try_get_base_address(module_name: &str) -> Option<usize> {
|
||||||
|
let w_module_name = wide_str(module_name);
|
||||||
|
|
||||||
|
match GetModuleHandleW(PCWSTR::from_raw(w_module_name.as_ptr())) {
|
||||||
|
Ok(module) => Some(module.0 as usize),
|
||||||
|
Err(_) => None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// VMProtect hooks NtProtectVirtualMemory to prevent changing protection of executable segments
|
||||||
|
// We use this trick to remove hook
|
||||||
|
pub unsafe fn disable_memprotect_guard() {
|
||||||
|
let ntdll = wide_str("ntdll.dll");
|
||||||
|
let ntdll = GetModuleHandleW(PCWSTR::from_raw(ntdll.as_ptr())).unwrap();
|
||||||
|
let proc_addr = GetProcAddress(
|
||||||
|
ntdll,
|
||||||
|
PCSTR::from_raw(c"NtProtectVirtualMemory".to_bytes_with_nul().as_ptr()),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
let nt_query = GetProcAddress(ntdll, PCSTR::from_raw(c"NtQuerySection".to_bytes_with_nul().as_ptr())).unwrap();
|
||||||
|
|
||||||
|
let mut old_prot = PAGE_PROTECTION_FLAGS(0);
|
||||||
|
VirtualProtect(
|
||||||
|
proc_addr as *const usize as *mut c_void,
|
||||||
|
1,
|
||||||
|
PAGE_EXECUTE_READWRITE,
|
||||||
|
&mut old_prot,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let routine = nt_query as *mut u32;
|
||||||
|
let routine_val = *(routine as *const usize);
|
||||||
|
|
||||||
|
let lower_bits_mask = !(0xFFu64 << 32);
|
||||||
|
let lower_bits = routine_val & lower_bits_mask as usize;
|
||||||
|
|
||||||
|
let offset_val = *((routine as usize + 4) as *const u32);
|
||||||
|
let upper_bits = ((offset_val as usize).wrapping_sub(1) as usize) << 32;
|
||||||
|
|
||||||
|
let result = lower_bits | upper_bits;
|
||||||
|
|
||||||
|
*(proc_addr as *mut usize) = result;
|
||||||
|
|
||||||
|
VirtualProtect(
|
||||||
|
proc_addr as *const usize as *mut c_void,
|
||||||
|
1,
|
||||||
|
old_prot,
|
||||||
|
&mut old_prot,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
}
|
54
src/version.rs
Normal file
54
src/version.rs
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
use libloading::{Error, Library, Symbol};
|
||||||
|
use std::env;
|
||||||
|
use std::ffi::CStr;
|
||||||
|
|
||||||
|
static FUNCTION_NAMES: &[&CStr] = &[
|
||||||
|
c"GetFileVersionInfoA",
|
||||||
|
c"GetFileVersionInfoByHandle",
|
||||||
|
c"GetFileVersionInfoExA",
|
||||||
|
c"GetFileVersionInfoExW",
|
||||||
|
c"GetFileVersionInfoSizeA",
|
||||||
|
c"GetFileVersionInfoSizeExA",
|
||||||
|
c"GetFileVersionInfoSizeExW",
|
||||||
|
c"GetFileVersionInfoSizeW",
|
||||||
|
c"GetFileVersionInfoW",
|
||||||
|
c"VerFindFileA",
|
||||||
|
c"VerFindFileW",
|
||||||
|
c"VerInstallFileA",
|
||||||
|
c"VerInstallFileW",
|
||||||
|
c"VerLanguageNameA",
|
||||||
|
c"VerLanguageNameW",
|
||||||
|
c"VerQueryValueA",
|
||||||
|
c"VerQueryValueW",
|
||||||
|
];
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
static mut ORIGINAL_FUNCTIONS: [*const usize; 17] = [0 as *const usize; 17];
|
||||||
|
|
||||||
|
pub struct VersionDllProxy {
|
||||||
|
library: Library,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl VersionDllProxy {
|
||||||
|
pub fn new() -> Result<Self, Box<dyn std::error::Error>> {
|
||||||
|
let system_directory = env::var("windir")? + ("\\System32\\");
|
||||||
|
let dll_path = system_directory + "version.dll";
|
||||||
|
let library = unsafe { Library::new(dll_path) }?;
|
||||||
|
Ok(Self { library })
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_function<T>(&self, func_name: &CStr) -> Result<Symbol<T>, Error> {
|
||||||
|
unsafe { self.library.get(func_name.to_bytes_with_nul()) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn load_functions(&self) -> Result<(), Error> {
|
||||||
|
for (i, &name) in FUNCTION_NAMES.iter().enumerate() {
|
||||||
|
let fn_ptr = self.get_function::<Symbol<*mut usize>>(name)?;
|
||||||
|
unsafe { ORIGINAL_FUNCTIONS[i] = **fn_ptr };
|
||||||
|
println!("Loaded function {}@{:p}", name.to_str().unwrap(), unsafe {
|
||||||
|
ORIGINAL_FUNCTIONS[i]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
112
version.asm
Normal file
112
version.asm
Normal file
|
@ -0,0 +1,112 @@
|
||||||
|
ifdef RAX
|
||||||
|
.code
|
||||||
|
extern ORIGINAL_FUNCTIONS:QWORD
|
||||||
|
GetFileVersionInfoA proc
|
||||||
|
jmp QWORD ptr ORIGINAL_FUNCTIONS[0 * 8]
|
||||||
|
GetFileVersionInfoA endp
|
||||||
|
GetFileVersionInfoByHandle proc
|
||||||
|
jmp QWORD ptr ORIGINAL_FUNCTIONS[1 * 8]
|
||||||
|
GetFileVersionInfoByHandle endp
|
||||||
|
GetFileVersionInfoExA proc
|
||||||
|
jmp QWORD ptr ORIGINAL_FUNCTIONS[2 * 8]
|
||||||
|
GetFileVersionInfoExA endp
|
||||||
|
GetFileVersionInfoExW proc
|
||||||
|
jmp QWORD ptr ORIGINAL_FUNCTIONS[3 * 8]
|
||||||
|
GetFileVersionInfoExW endp
|
||||||
|
GetFileVersionInfoSizeA proc
|
||||||
|
jmp QWORD ptr ORIGINAL_FUNCTIONS[4 * 8]
|
||||||
|
GetFileVersionInfoSizeA endp
|
||||||
|
GetFileVersionInfoSizeExA proc
|
||||||
|
jmp QWORD ptr ORIGINAL_FUNCTIONS[5 * 8]
|
||||||
|
GetFileVersionInfoSizeExA endp
|
||||||
|
GetFileVersionInfoSizeExW proc
|
||||||
|
jmp QWORD ptr ORIGINAL_FUNCTIONS[6 * 8]
|
||||||
|
GetFileVersionInfoSizeExW endp
|
||||||
|
GetFileVersionInfoSizeW proc
|
||||||
|
jmp QWORD ptr ORIGINAL_FUNCTIONS[7 * 8]
|
||||||
|
GetFileVersionInfoSizeW endp
|
||||||
|
GetFileVersionInfoW proc
|
||||||
|
jmp QWORD ptr ORIGINAL_FUNCTIONS[8 * 8]
|
||||||
|
GetFileVersionInfoW endp
|
||||||
|
VerFindFileA proc
|
||||||
|
jmp QWORD ptr ORIGINAL_FUNCTIONS[9 * 8]
|
||||||
|
VerFindFileA endp
|
||||||
|
VerFindFileW proc
|
||||||
|
jmp QWORD ptr ORIGINAL_FUNCTIONS[10 * 8]
|
||||||
|
VerFindFileW endp
|
||||||
|
VerInstallFileA proc
|
||||||
|
jmp QWORD ptr ORIGINAL_FUNCTIONS[11 * 8]
|
||||||
|
VerInstallFileA endp
|
||||||
|
VerInstallFileW proc
|
||||||
|
jmp QWORD ptr ORIGINAL_FUNCTIONS[12 * 8]
|
||||||
|
VerInstallFileW endp
|
||||||
|
VerLanguageNameA proc
|
||||||
|
jmp QWORD ptr ORIGINAL_FUNCTIONS[13 * 8]
|
||||||
|
VerLanguageNameA endp
|
||||||
|
VerLanguageNameW proc
|
||||||
|
jmp QWORD ptr ORIGINAL_FUNCTIONS[14 * 8]
|
||||||
|
VerLanguageNameW endp
|
||||||
|
VerQueryValueA proc
|
||||||
|
jmp QWORD ptr ORIGINAL_FUNCTIONS[15 * 8]
|
||||||
|
VerQueryValueA endp
|
||||||
|
VerQueryValueW proc
|
||||||
|
jmp QWORD ptr ORIGINAL_FUNCTIONS[16 * 8]
|
||||||
|
VerQueryValueW endp
|
||||||
|
else
|
||||||
|
.model flat, C
|
||||||
|
.stack 4096
|
||||||
|
.code
|
||||||
|
extern ORIGINAL_FUNCTIONS:DWORD
|
||||||
|
GetFileVersionInfoA proc
|
||||||
|
jmp DWORD ptr ORIGINAL_FUNCTIONS[0 * 4]
|
||||||
|
GetFileVersionInfoA endp
|
||||||
|
GetFileVersionInfoByHandle proc
|
||||||
|
jmp DWORD ptr ORIGINAL_FUNCTIONS[1 * 4]
|
||||||
|
GetFileVersionInfoByHandle endp
|
||||||
|
GetFileVersionInfoExA proc
|
||||||
|
jmp DWORD ptr ORIGINAL_FUNCTIONS[2 * 4]
|
||||||
|
GetFileVersionInfoExA endp
|
||||||
|
GetFileVersionInfoExW proc
|
||||||
|
jmp DWORD ptr ORIGINAL_FUNCTIONS[3 * 4]
|
||||||
|
GetFileVersionInfoExW endp
|
||||||
|
GetFileVersionInfoSizeA proc
|
||||||
|
jmp DWORD ptr ORIGINAL_FUNCTIONS[4 * 4]
|
||||||
|
GetFileVersionInfoSizeA endp
|
||||||
|
GetFileVersionInfoSizeExA proc
|
||||||
|
jmp DWORD ptr ORIGINAL_FUNCTIONS[5 * 4]
|
||||||
|
GetFileVersionInfoSizeExA endp
|
||||||
|
GetFileVersionInfoSizeExW proc
|
||||||
|
jmp DWORD ptr ORIGINAL_FUNCTIONS[6 * 4]
|
||||||
|
GetFileVersionInfoSizeExW endp
|
||||||
|
GetFileVersionInfoSizeW proc
|
||||||
|
jmp DWORD ptr ORIGINAL_FUNCTIONS[7 * 4]
|
||||||
|
GetFileVersionInfoSizeW endp
|
||||||
|
GetFileVersionInfoW proc
|
||||||
|
jmp DWORD ptr ORIGINAL_FUNCTIONS[8 * 4]
|
||||||
|
GetFileVersionInfoW endp
|
||||||
|
VerFindFileA proc
|
||||||
|
jmp DWORD ptr ORIGINAL_FUNCTIONS[9 * 4]
|
||||||
|
VerFindFileA endp
|
||||||
|
VerFindFileW proc
|
||||||
|
jmp DWORD ptr ORIGINAL_FUNCTIONS[10 * 4]
|
||||||
|
VerFindFileW endp
|
||||||
|
VerInstallFileA proc
|
||||||
|
jmp DWORD ptr ORIGINAL_FUNCTIONS[11 * 4]
|
||||||
|
VerInstallFileA endp
|
||||||
|
VerInstallFileW proc
|
||||||
|
jmp DWORD ptr ORIGINAL_FUNCTIONS[12 * 4]
|
||||||
|
VerInstallFileW endp
|
||||||
|
VerLanguageNameA proc
|
||||||
|
jmp DWORD ptr ORIGINAL_FUNCTIONS[13 * 4]
|
||||||
|
VerLanguageNameA endp
|
||||||
|
VerLanguageNameW proc
|
||||||
|
jmp DWORD ptr ORIGINAL_FUNCTIONS[14 * 4]
|
||||||
|
VerLanguageNameW endp
|
||||||
|
VerQueryValueA proc
|
||||||
|
jmp DWORD ptr ORIGINAL_FUNCTIONS[15 * 4]
|
||||||
|
VerQueryValueA endp
|
||||||
|
VerQueryValueW proc
|
||||||
|
jmp DWORD ptr ORIGINAL_FUNCTIONS[16 * 4]
|
||||||
|
VerQueryValueW endp
|
||||||
|
endif
|
||||||
|
end
|
19
version.def
Normal file
19
version.def
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
|
||||||
|
EXPORTS
|
||||||
|
GetFileVersionInfoA
|
||||||
|
GetFileVersionInfoByHandle
|
||||||
|
GetFileVersionInfoExA
|
||||||
|
GetFileVersionInfoExW
|
||||||
|
GetFileVersionInfoSizeA
|
||||||
|
GetFileVersionInfoSizeExA
|
||||||
|
GetFileVersionInfoSizeExW
|
||||||
|
GetFileVersionInfoSizeW
|
||||||
|
GetFileVersionInfoW
|
||||||
|
VerFindFileA
|
||||||
|
VerFindFileW
|
||||||
|
VerInstallFileA
|
||||||
|
VerInstallFileW
|
||||||
|
VerLanguageNameA
|
||||||
|
VerLanguageNameW
|
||||||
|
VerQueryValueA
|
||||||
|
VerQueryValueW
|
Loading…
Reference in a new issue