mirror of
https://github.com/beerpiss/saekawa.git
synced 2024-11-27 17:00:50 +01:00
fix(updater): just get the address by loading the library instead of relying on the linker to do what we want
This commit is contained in:
parent
7145efc237
commit
4fee755ab4
3
Cargo.lock
generated
3
Cargo.lock
generated
@ -952,13 +952,14 @@ checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "saekawa"
|
name = "saekawa"
|
||||||
version = "0.4.3"
|
version = "0.4.4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aes",
|
"aes",
|
||||||
"cbc",
|
"cbc",
|
||||||
"chrono",
|
"chrono",
|
||||||
"confy",
|
"confy",
|
||||||
"crochet",
|
"crochet",
|
||||||
|
"dlopen2",
|
||||||
"env_logger",
|
"env_logger",
|
||||||
"faster-hex",
|
"faster-hex",
|
||||||
"flate2",
|
"flate2",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "saekawa"
|
name = "saekawa"
|
||||||
version = "0.4.3"
|
version = "0.4.4"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
license = "0BSD"
|
license = "0BSD"
|
||||||
|
|
||||||
@ -20,6 +20,7 @@ cbc = "0.1.2"
|
|||||||
chrono = "0.4.38"
|
chrono = "0.4.38"
|
||||||
confy = "0.6.1"
|
confy = "0.6.1"
|
||||||
crochet = "0.2.3"
|
crochet = "0.2.3"
|
||||||
|
dlopen2 = "0.6.0"
|
||||||
env_logger = { version = "0.11.3", default-features = false }
|
env_logger = { version = "0.11.3", default-features = false }
|
||||||
faster-hex = "0.9.0"
|
faster-hex = "0.9.0"
|
||||||
flate2 = "1.0.30"
|
flate2 = "1.0.30"
|
||||||
|
@ -22,7 +22,7 @@ pub static mut REPLCE_FILE_W_PTR: PROC = ptr::null_mut();
|
|||||||
|
|
||||||
#[link_section = ".rtext"]
|
#[link_section = ".rtext"]
|
||||||
#[used]
|
#[used]
|
||||||
pub static mut LOAD_LIBRARY_W_POINTER: PROC = ptr::null_mut();
|
pub static mut LOAD_LIBRARY_W_PTR: PROC = ptr::null_mut();
|
||||||
|
|
||||||
#[link_section = ".rtext"]
|
#[link_section = ".rtext"]
|
||||||
#[used]
|
#[used]
|
||||||
@ -60,7 +60,7 @@ pub unsafe extern "system" fn replace_with_new_library(parameter: *const c_void)
|
|||||||
std::mem::transmute::<PROC, GetModuleFileNameAFn>(GET_MODULE_FILE_NAME_A_PTR);
|
std::mem::transmute::<PROC, GetModuleFileNameAFn>(GET_MODULE_FILE_NAME_A_PTR);
|
||||||
let GetProcessHeap = std::mem::transmute::<PROC, GetProcessHeapFn>(GET_PROCESS_HEAP_PTR);
|
let GetProcessHeap = std::mem::transmute::<PROC, GetProcessHeapFn>(GET_PROCESS_HEAP_PTR);
|
||||||
let ReplaceFileW = std::mem::transmute::<PROC, ReplaceFileWFn>(REPLCE_FILE_W_PTR);
|
let ReplaceFileW = std::mem::transmute::<PROC, ReplaceFileWFn>(REPLCE_FILE_W_PTR);
|
||||||
let LoadLibraryW = std::mem::transmute::<PROC, LoadLibraryWFn>(LOAD_LIBRARY_W_POINTER);
|
let LoadLibraryW = std::mem::transmute::<PROC, LoadLibraryWFn>(LOAD_LIBRARY_W_PTR);
|
||||||
let HeapFree = std::mem::transmute::<PROC, HeapFreeFn>(HEAP_FREE_PTR);
|
let HeapFree = std::mem::transmute::<PROC, HeapFreeFn>(HEAP_FREE_PTR);
|
||||||
let Sleep = std::mem::transmute::<PROC, SleepFn>(SLEEP_PTR);
|
let Sleep = std::mem::transmute::<PROC, SleepFn>(SLEEP_PTR);
|
||||||
|
|
||||||
@ -86,7 +86,7 @@ pub unsafe extern "system" fn replace_with_new_library(parameter: *const c_void)
|
|||||||
ptr::null_mut(),
|
ptr::null_mut(),
|
||||||
);
|
);
|
||||||
|
|
||||||
if result > 0 {
|
if result != 0 {
|
||||||
LoadLibraryW((*args).old.as_ptr());
|
LoadLibraryW((*args).old.as_ptr());
|
||||||
} else {
|
} else {
|
||||||
LoadLibraryW((*args).new.as_ptr());
|
LoadLibraryW((*args).new.as_ptr());
|
||||||
|
@ -14,35 +14,26 @@ use snafu::{prelude::Snafu, ResultExt};
|
|||||||
use widestring::U16CString;
|
use widestring::U16CString;
|
||||||
use winapi::{
|
use winapi::{
|
||||||
shared::{
|
shared::{
|
||||||
minwindef::{BOOL, DWORD, HMODULE, LPVOID, PROC},
|
minwindef::PROC,
|
||||||
ntdef::{LPCWSTR, LPSTR},
|
|
||||||
winerror::{
|
winerror::{
|
||||||
CERT_E_CHAINING, CERT_E_EXPIRED, CERT_E_UNTRUSTEDROOT, CRYPT_E_SECURITY_SETTINGS,
|
CERT_E_CHAINING, CERT_E_EXPIRED, CERT_E_UNTRUSTEDROOT, CRYPT_E_SECURITY_SETTINGS,
|
||||||
TRUST_E_BAD_DIGEST, TRUST_E_EXPLICIT_DISTRUST, TRUST_E_NOSIGNATURE,
|
TRUST_E_BAD_DIGEST, TRUST_E_EXPLICIT_DISTRUST, TRUST_E_NOSIGNATURE,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
um::{
|
um::{
|
||||||
heapapi::HeapAlloc,
|
errhandlingapi::GetLastError, heapapi::{GetProcessHeap, HeapAlloc}, memoryapi::{VirtualAlloc, VirtualProtect}, minwinbase::LMEM_ZEROINIT, processthreadsapi::CreateThread, softpub::WINTRUST_ACTION_GENERIC_VERIFY_V2, winbase::LocalAlloc, wincrypt::{
|
||||||
memoryapi::{VirtualAlloc, VirtualProtect},
|
|
||||||
minwinbase::LMEM_ZEROINIT,
|
|
||||||
processthreadsapi::CreateThread,
|
|
||||||
softpub::WINTRUST_ACTION_GENERIC_VERIFY_V2,
|
|
||||||
winbase::LocalAlloc,
|
|
||||||
wincrypt::{
|
|
||||||
CertCloseStore, CertFindCertificateInStore, CryptMsgClose, CryptMsgGetParam,
|
CertCloseStore, CertFindCertificateInStore, CryptMsgClose, CryptMsgGetParam,
|
||||||
CryptQueryObject, CERT_FIND_SUBJECT_CERT, CERT_INFO,
|
CryptQueryObject, CERT_FIND_SUBJECT_CERT, CERT_INFO,
|
||||||
CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED, CERT_QUERY_FORMAT_FLAG_BINARY,
|
CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED, CERT_QUERY_FORMAT_FLAG_BINARY,
|
||||||
CERT_QUERY_OBJECT_FILE, CMSG_SIGNER_INFO_PARAM, HCERTSTORE, HCRYPTMSG,
|
CERT_QUERY_OBJECT_FILE, CMSG_SIGNER_INFO_PARAM, HCERTSTORE, HCRYPTMSG,
|
||||||
PCMSG_SIGNER_INFO, PKCS_7_ASN_ENCODING, X509_ASN_ENCODING,
|
PCMSG_SIGNER_INFO, PKCS_7_ASN_ENCODING, X509_ASN_ENCODING,
|
||||||
},
|
}, winnt::{
|
||||||
winnt::{
|
HEAP_ZERO_MEMORY, IMAGE_DOS_HEADER, IMAGE_NT_HEADERS32, IMAGE_SECTION_HEADER,
|
||||||
HANDLE, HEAP_ZERO_MEMORY, IMAGE_DOS_HEADER, IMAGE_NT_HEADERS32, IMAGE_SECTION_HEADER,
|
|
||||||
MEM_COMMIT, MEM_RESERVE, PAGE_EXECUTE_READ, PAGE_READWRITE,
|
MEM_COMMIT, MEM_RESERVE, PAGE_EXECUTE_READ, PAGE_READWRITE,
|
||||||
},
|
}, wintrust::{
|
||||||
wintrust::{
|
|
||||||
WinVerifyTrust, WINTRUST_DATA, WINTRUST_FILE_INFO, WTD_CHOICE_FILE, WTD_REVOKE_NONE,
|
WinVerifyTrust, WINTRUST_DATA, WINTRUST_FILE_INFO, WTD_CHOICE_FILE, WTD_REVOKE_NONE,
|
||||||
WTD_STATEACTION_CLOSE, WTD_STATEACTION_VERIFY, WTD_UI_NONE,
|
WTD_STATEACTION_CLOSE, WTD_STATEACTION_VERIFY, WTD_UI_NONE,
|
||||||
},
|
}
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -52,27 +43,6 @@ use crate::{
|
|||||||
helpers::winapi_ext::{get_module_file_name, LibraryHandle, ReadStringFnError},
|
helpers::winapi_ext::{get_module_file_name, LibraryHandle, ReadStringFnError},
|
||||||
};
|
};
|
||||||
|
|
||||||
// I don't know what the hell is going on with linking, but you have to link these manually,
|
|
||||||
// otherwise you end up with the addresses to the intermediary functions, which obviously
|
|
||||||
// doesn't exist once you unloads the original library.
|
|
||||||
#[link(name = "kernel32")]
|
|
||||||
extern "system" {
|
|
||||||
pub fn GetLastError() -> u32;
|
|
||||||
pub fn GetModuleFileNameA(hModule: HMODULE, lpFilename: LPSTR, nsize: DWORD) -> u32;
|
|
||||||
pub fn GetProcessHeap() -> HANDLE;
|
|
||||||
pub fn HeapFree(hHeap: HANDLE, dwFlags: DWORD, lpMem: LPVOID) -> BOOL;
|
|
||||||
pub fn LoadLibraryW(lpFileName: LPCWSTR) -> HMODULE;
|
|
||||||
pub fn ReplaceFileW(
|
|
||||||
lpReplacedFileName: LPCWSTR,
|
|
||||||
lpReplacementFileName: LPCWSTR,
|
|
||||||
lpBackupFileName: LPCWSTR,
|
|
||||||
dwReplaceFlags: DWORD,
|
|
||||||
lpExclude: LPVOID,
|
|
||||||
lpReserved: LPVOID,
|
|
||||||
) -> BOOL;
|
|
||||||
pub fn Sleep(dwMilliseconds: DWORD);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Snafu)]
|
#[derive(Debug, Snafu)]
|
||||||
#[allow(clippy::large_enum_variant)]
|
#[allow(clippy::large_enum_variant)]
|
||||||
pub enum SelfUpdateError {
|
pub enum SelfUpdateError {
|
||||||
@ -257,13 +227,16 @@ pub fn self_update(module: &LibraryHandle) -> Result<bool, SelfUpdateError> {
|
|||||||
//
|
//
|
||||||
// Thanks to DJTRACKERS and their fervidex hook for the approach.
|
// Thanks to DJTRACKERS and their fervidex hook for the approach.
|
||||||
unsafe {
|
unsafe {
|
||||||
external::GET_LAST_ERROR_PTR = GetLastError as PROC;
|
let kernel32 = dlopen2::raw::Library::open("kernel32.dll")
|
||||||
external::GET_MODULE_FILE_NAME_A_PTR = GetModuleFileNameA as PROC;
|
.expect("kernel32 missing on windows?");
|
||||||
external::GET_PROCESS_HEAP_PTR = GetProcessHeap as PROC;
|
|
||||||
external::HEAP_FREE_PTR = HeapFree as PROC;
|
external::GET_LAST_ERROR_PTR = kernel32.symbol("GetLastError").unwrap();
|
||||||
external::LOAD_LIBRARY_W_POINTER = LoadLibraryW as PROC;
|
external::GET_MODULE_FILE_NAME_A_PTR = kernel32.symbol("GetModuleFileNameA").unwrap();
|
||||||
external::REPLCE_FILE_W_PTR = ReplaceFileW as PROC;
|
external::GET_PROCESS_HEAP_PTR = kernel32.symbol("GetProcessHeap").unwrap();
|
||||||
external::SLEEP_PTR = Sleep as PROC;
|
external::HEAP_FREE_PTR = kernel32.symbol("HeapFree").unwrap();
|
||||||
|
external::LOAD_LIBRARY_W_PTR = kernel32.symbol("LoadLibraryW").unwrap();
|
||||||
|
external::REPLCE_FILE_W_PTR = kernel32.symbol("ReplaceFileW").unwrap();
|
||||||
|
external::SLEEP_PTR = kernel32.symbol("Sleep").unwrap();
|
||||||
|
|
||||||
debug!("Locating updater code...");
|
debug!("Locating updater code...");
|
||||||
let dos_header = module.handle() as *const IMAGE_DOS_HEADER;
|
let dos_header = module.handle() as *const IMAGE_DOS_HEADER;
|
||||||
@ -330,6 +303,7 @@ pub fn self_update(module: &LibraryHandle) -> Result<bool, SelfUpdateError> {
|
|||||||
&mut old_protect,
|
&mut old_protect,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// 0x00007FFB13A63A14
|
||||||
if result == 0 {
|
if result == 0 {
|
||||||
return Err(SelfUpdateError::FailedVirtualProtect {
|
return Err(SelfUpdateError::FailedVirtualProtect {
|
||||||
errno: GetLastError(),
|
errno: GetLastError(),
|
||||||
|
Loading…
Reference in New Issue
Block a user