|
| 1 | +use log::{debug, error, LevelFilter}; |
| 2 | +use std::{arch::global_asm, ffi::c_void}; |
| 3 | +use windows::Win32::{ |
| 4 | + Foundation::{GetLastError, WIN32_ERROR}, |
| 5 | + System::Memory::{VirtualProtect, PAGE_EXECUTE_READWRITE, PAGE_PROTECTION_FLAGS}, |
| 6 | +}; |
| 7 | +pub static TITLE: &str = concat!(" Weekly production (fixed)", "\0"); |
| 8 | +const WEEKLY_PRODUCTION_STRING_PTR: *mut *const u8 = 0x006A081C as _; |
| 9 | +static SEVEN: f32 = 7.0; |
| 10 | +static FTOL_ADDRESS: u32 = 0x00639C28; |
| 11 | +static CONTINUATION_ADDRESS: u32 = 0x005DEACC; |
| 12 | +static BARREL_PATCH_ADDRESS: u32 = 0x005DEA18; |
| 13 | +static BUNDLE_PATCH_ADDRESS: u32 = 0x005DEA73; |
| 14 | + |
| 15 | +#[no_mangle] |
| 16 | +pub unsafe extern "C" fn start() -> u32 { |
| 17 | + let _ = log::set_logger(&win_dbg_logger::DEBUGGER_LOGGER); |
| 18 | + log::set_max_level(LevelFilter::Trace); |
| 19 | + |
| 20 | + // Patch barrels |
| 21 | + let barrel_patch_address: u32 = (&barrel_ware_detour) as *const _ as _; |
| 22 | + let relative_barrel_patch_address: u32 = barrel_patch_address.wrapping_sub(BARREL_PATCH_ADDRESS) - 5; //TODO move pointer calcs to hooklet |
| 23 | + |
| 24 | + let mut barrel_patch: [u8; 5] = [0; 5]; |
| 25 | + barrel_patch[0] = 0xe9; |
| 26 | + barrel_patch[1..5].copy_from_slice(&relative_barrel_patch_address.to_le_bytes()); |
| 27 | + let patch_ptr: *mut u8 = BARREL_PATCH_ADDRESS as _; |
| 28 | + |
| 29 | + let mut old_flags: PAGE_PROTECTION_FLAGS = windows::Win32::System::Memory::PAGE_PROTECTION_FLAGS(0); |
| 30 | + if !VirtualProtect(patch_ptr as _, 5, PAGE_EXECUTE_READWRITE, &mut old_flags).as_bool() { |
| 31 | + let error: WIN32_ERROR = GetLastError(); |
| 32 | + error!("VirtualProtect PAGE_EXECUTE_READWRITE failed: {:?}", error); |
| 33 | + return 1; |
| 34 | + } |
| 35 | + |
| 36 | + debug!("Deploying barrel patch at {:x?}", barrel_patch_address as *const u32); |
| 37 | + patch_ptr.copy_from(barrel_patch.as_ptr(), barrel_patch.len()); |
| 38 | + |
| 39 | + if !VirtualProtect(patch_ptr as _, 5, old_flags, &mut old_flags).as_bool() { |
| 40 | + let error: WIN32_ERROR = GetLastError(); |
| 41 | + error!("VirtualProtect restore failed: {:?}", error); |
| 42 | + return 2; |
| 43 | + } |
| 44 | + |
| 45 | + // Patch bundles |
| 46 | + let bundle_patch_address: u32 = (&bundle_ware_detour) as *const _ as _; |
| 47 | + let relative_bundle_patch_address: u32 = bundle_patch_address.wrapping_sub(BUNDLE_PATCH_ADDRESS) - 5; //TODO move pointer calcs to hooklet |
| 48 | + |
| 49 | + let mut bundle_patch: [u8; 5] = [0; 5]; |
| 50 | + bundle_patch[0] = 0xe9; |
| 51 | + bundle_patch[1..5].copy_from_slice(&relative_bundle_patch_address.to_le_bytes()); |
| 52 | + let patch_ptr: *mut u8 = BUNDLE_PATCH_ADDRESS as _; |
| 53 | + |
| 54 | + let mut old_flags: PAGE_PROTECTION_FLAGS = windows::Win32::System::Memory::PAGE_PROTECTION_FLAGS(0); |
| 55 | + if !VirtualProtect(patch_ptr as _, 5, PAGE_EXECUTE_READWRITE, &mut old_flags).as_bool() { |
| 56 | + let error: WIN32_ERROR = GetLastError(); |
| 57 | + error!("VirtualProtect PAGE_EXECUTE_READWRITE failed: {:?}", error); |
| 58 | + return 1; |
| 59 | + } |
| 60 | + |
| 61 | + debug!("Deploying bundle patch at {:x?}", bundle_patch_address as *const u32); |
| 62 | + patch_ptr.copy_from(bundle_patch.as_ptr(), bundle_patch.len()); |
| 63 | + |
| 64 | + if !VirtualProtect(patch_ptr as _, 5, old_flags, &mut old_flags).as_bool() { |
| 65 | + let error: WIN32_ERROR = GetLastError(); |
| 66 | + error!("VirtualProtect restore failed: {:?}", error); |
| 67 | + return 2; |
| 68 | + } |
| 69 | + |
| 70 | + // Patch title |
| 71 | + *WEEKLY_PRODUCTION_STRING_PTR = TITLE.as_ptr(); |
| 72 | + 0 |
| 73 | +} |
| 74 | + |
| 75 | +extern "C" { |
| 76 | + static barrel_ware_detour: c_void; |
| 77 | + static bundle_ware_detour: c_void; |
| 78 | +} |
| 79 | + |
| 80 | +// Barrel wares |
| 81 | +global_asm!(" |
| 82 | +.global {barrel_ware_detour} |
| 83 | +{barrel_ware_detour}: |
| 84 | +shl edx,0x6 |
| 85 | +sub edx,eax |
| 86 | +lea ebp,[ecx+edx*2] |
| 87 | +fild DWORD PTR [esi+ebp*4+0x4] |
| 88 | +fstp DWORD PTR [esp+0x20] |
| 89 | +fld DWORD PTR [esp+0x20] |
| 90 | +fdiv DWORD PTR ds:0x66a91c |
| 91 | +fadd QWORD PTR ds:0x66a7d0 |
| 92 | +call [{ftol_addresss}] |
| 93 | +fild DWORD PTR [esi+ebp*4+0xc4] |
| 94 | +mov edi,eax |
| 95 | +fstp DWORD PTR [esp+0x20] |
| 96 | +fld DWORD PTR [esp+0x20] |
| 97 | +fdiv DWORD PTR ds:0x66a91c |
| 98 | +fmul DWORD PTR ds:{seven} |
| 99 | +fadd QWORD PTR ds:0x66a7d0 |
| 100 | +call [{ftol_addresss}] |
| 101 | +fild DWORD PTR [esp+0x18] |
| 102 | +fstp DWORD PTR [esp+0x20] |
| 103 | +fld DWORD PTR [esp+0x20] |
| 104 | +fdiv DWORD PTR ds:0x66a91c |
| 105 | +jmp [{continuation_address}] |
| 106 | +", |
| 107 | +barrel_ware_detour = sym barrel_ware_detour, |
| 108 | +ftol_addresss = sym FTOL_ADDRESS, |
| 109 | +seven = sym SEVEN, |
| 110 | +continuation_address = sym CONTINUATION_ADDRESS); |
| 111 | + |
| 112 | +// Bundle wares |
| 113 | +global_asm!(" |
| 114 | +.global {bundle_ware_detour} |
| 115 | +{bundle_ware_detour}: |
| 116 | +shl edx,0x6 |
| 117 | +sub edx,eax |
| 118 | +lea ebp,[ecx+edx*2] |
| 119 | +fild DWORD PTR [esi+ebp*4+0x4] |
| 120 | +fstp DWORD PTR [esp+0x20] |
| 121 | +fld DWORD PTR [esp+0x20] |
| 122 | +fdiv DWORD PTR ds:0x66a918 |
| 123 | +fadd QWORD PTR ds:0x66a7d0 |
| 124 | +call [{ftol_addresss}] |
| 125 | +fild DWORD PTR [esi+ebp*4+0xc4] |
| 126 | +mov edi,eax |
| 127 | +fstp DWORD PTR [esp+0x20] |
| 128 | +fld DWORD PTR [esp+0x20] |
| 129 | +fdiv DWORD PTR ds:0x66a918 |
| 130 | +fmul DWORD PTR ds:{seven} |
| 131 | +fadd QWORD PTR ds:0x66a7d0 |
| 132 | +call [{ftol_addresss}] |
| 133 | +fild DWORD PTR [esp+0x18] |
| 134 | +fstp DWORD PTR [esp+0x20] |
| 135 | +fld DWORD PTR [esp+0x20] |
| 136 | +fdiv DWORD PTR ds:0x66a918 |
| 137 | +jmp [{continuation_address}] |
| 138 | +", |
| 139 | +bundle_ware_detour = sym bundle_ware_detour, |
| 140 | +ftol_addresss = sym FTOL_ADDRESS, |
| 141 | +seven = sym SEVEN, |
| 142 | +continuation_address = sym CONTINUATION_ADDRESS); |
0 commit comments