From 8225a591d57131c6897ddfaae8d4c5b8034fe032 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Linus=20Unneb=C3=A4ck?= Date: Wed, 11 Sep 2024 23:01:19 +0200 Subject: [PATCH] implement kernel32 SizeofResource --- win32/dll/kernel32.dll | Bin 6144 -> 6144 bytes win32/src/winapi/builtin.rs | 21 ++++++++--- win32/src/winapi/kernel32/init.rs | 4 ++- win32/src/winapi/kernel32/resource.rs | 48 ++++++++++++++++++++------ win32/src/winapi/types.rs | 4 +++ win32/src/winapi/user32/resource.rs | 4 +++ 6 files changed, 65 insertions(+), 16 deletions(-) diff --git a/win32/dll/kernel32.dll b/win32/dll/kernel32.dll index 9f447e7c07e12d3b33828fecbb658edcd7bf0a9b..02fcc8aef40116f4fe2ee3f9d5b589472bbf312d 100755 GIT binary patch delta 738 zcmXZWT}YF06vy%NA5-RVOB75Kq^(GEx)i|#MO2!BH&Y4IK*g77VX!d~e1m7|K)kSA zj|oPgM($1pAJ9a)Q7o{FA%b^WAl--td82~@zd;8+hx3EO;e-l9h0`H(jrVS4Bpfg; z-q4GbOLwTJ>YF~Oa@1#IQEixYo7rx(C%#i}Eas$tyF#Tz99fxearairl#;QieLb!~iBSiw{`A7WQ$3OC;xrWS{^KQG+MwKmZzEA&NC@ zVh0B}!3Au&qKPwCqy&%g3;|4F9vj%hPyEJTB;6Oe1s6);K@)m0g4bBUI$}7+IsU+& zCz1^}%HYk@L|Pd7F@`yO#2UWh0N-(nE0|n-jZ8S6qm3TZ~*1-pansUV-8WQVjKH7!WrVQx{+RsZO1;YA&nqn$f6PjY6wthBFtGk;=4wuxVNUJHpuGu1C(MLJ`F= zd#{6gxk%)X`NU?osF3kIyG?hNiumvpAw-~K3iDXSHzaX@G%RHzxhO^@9-{?a2;&XL zu!wbh#SiS^7-z^R7jcw}E?$-fv?GitKH>{@@Dr!F!Y%A>5f`f9$1}Xb0LC$g4J2@g z6I?>85Xnagd}v0nLKo>{d5ak=U>)1o!x2(A$6sW4MDpN33F;9*7kV*@&q&}H=lF*# zFCDny#|ym1JDr%o99FQ2EhMmy6w;7N9-tO}1kr;b%wQ2~*g_Hq_>Bull}HYXP={9Z zAcBrjVhXcZ!UmE^A&nc@sznOmMm?I*hL;GT4}*we+Pr??QD$*&yUiSVIIN6-a^3;t CvxT_; diff --git a/win32/src/winapi/builtin.rs b/win32/src/winapi/builtin.rs index 8b9de74f..e0e34224 100644 --- a/win32/src/winapi/builtin.rs +++ b/win32/src/winapi/builtin.rs @@ -2765,8 +2765,8 @@ pub mod kernel32 { } pub unsafe fn LoadResource(machine: &mut Machine, esp: u32) -> u32 { let mem = machine.mem().detach(); - let hModule = ::from_stack(mem, esp + 4u32); - let hResInfo = ::from_stack(mem, esp + 8u32); + let hModule = ::from_stack(mem, esp + 4u32); + let hResInfo = ::from_stack(mem, esp + 8u32); winapi::kernel32::LoadResource(machine, hModule, hResInfo).to_raw() } pub unsafe fn LocalAlloc(machine: &mut Machine, esp: u32) -> u32 { @@ -2782,7 +2782,7 @@ pub mod kernel32 { } pub unsafe fn LockResource(machine: &mut Machine, esp: u32) -> u32 { let mem = machine.mem().detach(); - let hResData = ::from_stack(mem, esp + 4u32); + let hResData = ::from_stack(mem, esp + 4u32); winapi::kernel32::LockResource(machine, hResData).to_raw() } pub unsafe fn MulDiv(machine: &mut Machine, esp: u32) -> u32 { @@ -2949,6 +2949,12 @@ pub mod kernel32 { winapi::kernel32::SetUnhandledExceptionFilter(machine, _lpTopLevelExceptionFilter) .to_raw() } + pub unsafe fn SizeofResource(machine: &mut Machine, esp: u32) -> u32 { + let mem = machine.mem().detach(); + let hModule = ::from_stack(mem, esp + 4u32); + let hResInfo = ::from_stack(mem, esp + 8u32); + winapi::kernel32::SizeofResource(machine, hModule, hResInfo).to_raw() + } pub unsafe fn Sleep(machine: &mut Machine, esp: u32) -> u32 { let mem = machine.mem().detach(); let dwMilliseconds = ::from_stack(mem, esp + 4u32); @@ -3946,6 +3952,12 @@ pub mod kernel32 { stack_consumed: 4u32, is_async: false, }; + pub const SizeofResource: Shim = Shim { + name: "SizeofResource", + func: impls::SizeofResource, + stack_consumed: 8u32, + is_async: false, + }; pub const Sleep: Shim = Shim { name: "Sleep", func: impls::Sleep, @@ -4085,7 +4097,7 @@ pub mod kernel32 { is_async: true, }; } - const SHIMS: [Shim; 148usize] = [ + const SHIMS: [Shim; 149usize] = [ shims::AcquireSRWLockExclusive, shims::AcquireSRWLockShared, shims::AddVectoredExceptionHandler, @@ -4211,6 +4223,7 @@ pub mod kernel32 { shims::SetThreadPriority, shims::SetThreadStackGuarantee, shims::SetUnhandledExceptionFilter, + shims::SizeofResource, shims::Sleep, shims::SystemTimeToFileTime, shims::TlsAlloc, diff --git a/win32/src/winapi/kernel32/init.rs b/win32/src/winapi/kernel32/init.rs index 031c714c..f1e36a0b 100644 --- a/win32/src/winapi/kernel32/init.rs +++ b/win32/src/winapi/kernel32/init.rs @@ -1,6 +1,6 @@ //! Process initialization and startup. -use super::{FindHandle, Mappings, DLL, HMODULE, STDERR_HFILE, STDOUT_HFILE}; +use super::{FindHandle, Mappings, ResourceHandle, DLL, HMODULE, STDERR_HFILE, STDOUT_HFILE}; use crate::{ machine::MemImpl, pe, @@ -209,6 +209,7 @@ pub struct State { pub dlls: HashMap, pub resources: pe::IMAGE_DATA_DIRECTORY, + pub resource_handles: Handles, pub files: Handles>, @@ -248,6 +249,7 @@ impl State { env: env_addr, cmdline, resources: Default::default(), + resource_handles: Default::default(), } } diff --git a/win32/src/winapi/kernel32/resource.rs b/win32/src/winapi/kernel32/resource.rs index 9bd0e062..e09763d3 100644 --- a/win32/src/winapi/kernel32/resource.rs +++ b/win32/src/winapi/kernel32/resource.rs @@ -1,6 +1,7 @@ #![allow(non_snake_case)] use crate::winapi::kernel32::HMODULE; +use crate::winapi::types::HRSRC; use crate::winapi::user32::HINSTANCE; use crate::{ pe, @@ -12,6 +13,7 @@ use crate::{ Machine, }; use memory::Mem; +use std::ops::Range; const TRACE_CONTEXT: &'static str = "kernel32/resource"; @@ -19,6 +21,8 @@ fn IS_INTRESOURCE(x: u32) -> bool { x >> 16 == 0 } +pub struct ResourceHandle(HMODULE, Range); + /// ResourceKey is the type of queries into the Windows resources system, including /// e.g. LoadResource() as well as LoadBitmap() etc. /// It's parameterized over the type of name to handle both A() and W() variants. @@ -77,18 +81,18 @@ pub fn find_resource<'a>( hInstance: HINSTANCE, typ: ResourceKey<&Str16>, name: ResourceKey<&Str16>, -) -> Option<&'a [u8]> { +) -> Option> { let image = mem.slice(hInstance..); if hInstance == kernel32.image_base { let section = kernel32.resources.as_slice(image)?; - Some(&image[pe::find_resource(section, typ.into_pe(), name.into_pe())?]) + pe::find_resource(section, typ.into_pe(), name.into_pe()) } else { let dll = kernel32.dlls.get(&HMODULE::from_raw(hInstance))?; match dll.dll.resources.clone() { None => return None, Some(resources) => { let section = resources.as_slice(image)?; - Some(&image[pe::find_resource(section, typ.into_pe(), name.into_pe())?]) + pe::find_resource(section, typ.into_pe(), name.into_pe()) } } } @@ -100,7 +104,7 @@ pub fn FindResourceA( hModule: HMODULE, lpName: ResourceKey<&str>, lpType: ResourceKey<&str>, -) -> u32 { +) -> HRSRC { let name = lpName.to_string16(); let type_ = lpType.to_string16(); FindResourceW(machine, hModule, name.as_ref(), type_.as_ref()) @@ -112,7 +116,7 @@ pub fn FindResourceW( hModule: HMODULE, lpName: ResourceKey<&Str16>, lpType: ResourceKey<&Str16>, -) -> u32 { +) -> HRSRC { match find_resource( &machine.state.kernel32, machine.mem(), @@ -120,17 +124,39 @@ pub fn FindResourceW( lpType, lpName, ) { - None => 0, - Some(mem) => machine.mem().offset_of(mem.as_ptr()), + None => HRSRC::null(), + Some(mem) => { + let handle = ResourceHandle(hModule.clone(), mem); + machine.state.kernel32.resource_handles.add(handle) + }, } } #[win32_derive::dllexport] -pub fn LoadResource(_machine: &mut Machine, hModule: u32, hResInfo: u32) -> u32 { - hResInfo +pub fn LoadResource(machine: &mut Machine, hModule: HMODULE, hResInfo: HRSRC) -> u32 { + hResInfo.to_raw() } #[win32_derive::dllexport] -pub fn LockResource(_machine: &mut Machine, hResData: u32) -> u32 { - hResData +pub fn LockResource(machine: &mut Machine, hResData: HRSRC) -> u32 { + let handle = match machine.state.kernel32.resource_handles.get(hResData) { + None => return 0, + Some(handle) => handle, + }; + + let mem = machine.mem(); + let hInstance = handle.0.to_raw(); + let image = mem.slice(hInstance..); + + let resource = &image[handle.1.clone()]; + + machine.mem().offset_of(resource.as_ptr()) +} + +#[win32_derive::dllexport] +pub fn SizeofResource(machine: &mut Machine, hModule: HMODULE, hResInfo: HRSRC) -> u32 { + match machine.state.kernel32.resource_handles.get(hResInfo) { + None => 0, + Some(handle) => handle.1.len() as u32, + } } diff --git a/win32/src/winapi/types.rs b/win32/src/winapi/types.rs index f02caa6d..a9bfbffe 100644 --- a/win32/src/winapi/types.rs +++ b/win32/src/winapi/types.rs @@ -15,6 +15,10 @@ pub type HFILE = HANDLE; pub struct HFINDT; pub type HFIND = HANDLE; +#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] +pub struct HRSRCT; +pub type HRSRC = HANDLE; + #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] pub struct HWNDT; pub type HWND = HANDLE; diff --git a/win32/src/winapi/user32/resource.rs b/win32/src/winapi/user32/resource.rs index 59753b8f..d859bb6f 100644 --- a/win32/src/winapi/user32/resource.rs +++ b/win32/src/winapi/user32/resource.rs @@ -75,6 +75,8 @@ fn load_bitmap( ResourceKey::Id(pe::RT::BITMAP as u32), name, )?; + let image = machine.mem().slice(hInstance..); + let buf = &image[buf]; let bmp = BitmapRGBA32::parse(buf, None); Some( machine @@ -166,6 +168,8 @@ fn find_string(machine: &Machine, hInstance: HINSTANCE, uID: u32) -> Option<&[u8 ResourceKey::Id(pe::RT::STRING as u32), ResourceKey::Id(resource_id), )?; + let image = machine.mem().slice(hInstance..); + let block = &image[block]; // Each block is a sequence of two byte length-prefixed strings. // Iterate through them to find the requested index.