From 699468bbc3ebba2dfe295c119471a43c4e24802e Mon Sep 17 00:00:00 2001 From: Truman Kilen Date: Tue, 29 Aug 2023 17:09:04 -0500 Subject: [PATCH 1/4] WIP DRG static reflection data extraction --- patternsleuth/src/patterns.rs | 468 +++++++++++++++++++++++++++++++ patternsleuth_scanner/src/lib.rs | 8 +- 2 files changed, 470 insertions(+), 6 deletions(-) diff --git a/patternsleuth/src/patterns.rs b/patternsleuth/src/patterns.rs index e9c1b00..03236b6 100644 --- a/patternsleuth/src/patterns.rs +++ b/patternsleuth/src/patterns.rs @@ -73,6 +73,8 @@ pub enum Sig { AES, Lock, + ClassInitializers, + StaticClass, } pub fn get_patterns() -> Result> { @@ -1474,6 +1476,21 @@ pub fn get_patterns() -> Result> { Pattern::from_bytes("Illegal call to StaticFindObjectFast".encode_utf16().flat_map(u16::to_le_bytes).collect())?, xref::resolve, ), + + PatternConfig::new( + Sig::ClassInitializers, + "ClassInitializers".to_string(), + None, + Pattern::new("48 83 EC 48 33 C0 4C 8D ?? ?? ?? ?? ?? 48 89 44 24 30 4C 8D ?? ?? ?? ?? ?? 48 89 44 24 28 48 8D ?? ?? ?? ?? ?? 48 8D ?? ?? ?? ?? ?? 88 44 24 20 E8 ?? ?? ?? ?? 48 83 C4 48 C3")?, + class_initializers::resolve, + ), + PatternConfig::new( + Sig::StaticClass, + "StaticClass".to_string(), + None, + class_initializers::pattern_static_class().clone(), + class_initializers::resolve_static_class, + ), ]) } @@ -1899,3 +1916,454 @@ mod signing_key { } } } + +mod class_initializers { + use std::{io::BufRead, sync::OnceLock}; + + use super::*; + + use byteorder::{ReadBytesExt, LE}; + + pub fn pattern_static_class() -> &'static Pattern { + static PATTERN: OnceLock = OnceLock::new(); + PATTERN.get_or_init(|| { + Pattern::new( + r#" +4C 8B DC +48 81 EC 88 00 00 00 +48 8B ?? ?? ?? ?? ?? +48 85 C0 +0F 85 ?? ?? ?? ?? +33 C9 +48 8D ?? ?? ?? ?? ?? +49 89 4B F0 +4C 8D ?? [ ?? ?? ?? ?? ] +88 4C 24 70 +4C 8D ?? ?? ?? ?? ?? +49 89 43 E0 +48 8D ?? [ ?? ?? ?? ?? ] +48 8D ?? ?? ?? ?? ?? +49 89 43 D8 +48 8D ?? ?? ?? ?? ?? +49 89 43 D0 +48 8D ?? ?? ?? ?? ?? +49 89 43 C8 +48 8D ?? ?? ?? ?? ?? +49 89 43 C0 +48 8D ?? ?? ?? ?? ?? +49 89 43 B8 +49 89 4B B0 +48 8D ?? [ ?? ?? ?? ?? ] +C7 44 24 30 [ ?? ?? ?? ?? ] +C7 44 24 28 [ ?? ?? ?? ?? ] +C7 44 24 20 [ ?? ?? ?? ?? ] +E8 ?? ?? ?? ?? +48 8B ?? ?? ?? ?? ?? +48 81 C4 88 00 00 00 +C3"#, + ) + .unwrap() + }) + } + + pub fn pattern_static_class2() -> &'static Pattern { + static PATTERN: OnceLock = OnceLock::new(); + PATTERN.get_or_init(|| { + Pattern::new( + r#" +4C 8B DC +48 81 EC 88 00 00 00 +48 8B ?? ?? ?? ?? ?? +48 85 C0 +0F 85 ?? ?? ?? ?? +33 C9 +48 8D ?? ?? ?? ?? ?? +49 89 4B F0 +4C 8D ?? [ ?? ?? ?? ?? ] +88 4C 24 70 +4C 8D ?? ?? ?? ?? ?? +49 89 43 E0 +48 8D ?? [ ?? ?? ?? ?? ] +49 89 43 D8 +48 8D ?? ?? ?? ?? ?? +49 89 43 D0 +48 8D ?? ?? ?? ?? ?? +49 89 43 C8 +48 8D ?? ?? ?? ?? ?? +49 89 43 C0 +48 8D ?? ?? ?? ?? ?? +49 89 43 B8 +49 89 4B B0 +48 8D ?? [ ?? ?? ?? ?? ] +C7 44 24 30 ?? ?? ?? ?? +C7 44 24 28 ?? ?? ?? ?? +C7 44 24 20 ?? ?? ?? ?? +E8 ?? ?? ?? ?? +48 8B ?? ?? ?? ?? ?? +48 81 C4 88 00 00 00 +C3 +"#, + ) + .unwrap() + }) + } + pub fn pattern_static_class3() -> &'static Pattern { + static PATTERN: OnceLock = OnceLock::new(); + PATTERN.get_or_init(|| { + Pattern::new( + r#" +4C 8B DC +48 81 EC 88 00 00 00 +48 8B ?? ?? ?? ?? ?? +48 85 C0 +0F 85 ?? ?? ?? ?? +49 89 43 F0 +4C 8D ?? [ ?? ?? ?? ?? ] +88 44 24 70 +4C 8D ?? ?? ?? ?? ?? +48 8D ?? ?? ?? ?? ?? +49 89 43 E0 +48 8D ?? [ ?? ?? ?? ?? ] +49 89 43 D8 +48 8D ?? [ ?? ?? ?? ?? ] +48 8D ?? ?? ?? ?? ?? +49 89 43 D0 +48 8D ?? ?? ?? ?? ?? +49 89 43 C8 +48 8D ?? ?? ?? ?? ?? +49 89 43 C0 +48 8D ?? ?? ?? ?? ?? +49 89 43 B8 +48 B8 ?? ?? ?? ?? ?? ?? ?? ?? +49 89 43 B0 +C7 44 24 30 [ ?? ?? ?? ?? ] +C7 44 24 28 [ ?? ?? ?? ?? ] +C7 44 24 20 [ ?? ?? ?? ?? ] +E8 ?? ?? ?? ?? +48 8B ?? ?? ?? ?? ?? +48 81 C4 88 00 00 00 +C3"#, + ) + .unwrap() + }) + } + pub fn pattern_static_class4() -> &'static Pattern { + static PATTERN: OnceLock = OnceLock::new(); + PATTERN.get_or_init(|| { + Pattern::new( + r#" +4C 8B DC +48 81 EC 88 00 00 00 +48 8B ?? ?? ?? ?? ?? +48 85 C0 +0F 85 ?? ?? ?? ?? +49 89 43 F0 +4C 8D ?? [ ?? ?? ?? ?? ] +88 44 24 70 +4C 8D ?? ?? ?? ?? ?? +48 8D ?? ?? ?? ?? ?? +49 89 43 E0 +48 8D ?? [ ?? ?? ?? ?? ] +48 8D ?? ?? ?? ?? ?? +49 89 43 D8 +48 8D ?? [ ?? ?? ?? ?? ] +48 8D ?? ?? ?? ?? ?? +49 89 43 D0 +48 8D ?? ?? ?? ?? ?? +49 89 43 C8 +48 8D ?? ?? ?? ?? ?? +49 89 43 C0 +48 8D ?? ?? ?? ?? ?? +49 89 43 B8 +48 B8 ?? ?? ?? ?? ?? ?? ?? ?? +49 89 43 B0 +C7 44 24 30 [ ?? ?? ?? ?? ] +C7 44 24 28 [ ?? ?? ?? ?? ] +C7 44 24 20 [ ?? ?? ?? ?? ] +E8 ?? ?? ?? ?? +48 8B ?? ?? ?? ?? ?? +48 81 C4 88 00 00 00 +C3 +"#, + ) + .unwrap() + }) + } + + fn read_string(ctx: &ResolveContext, address: usize) -> String { + let section = ctx.memory.get_section_containing(address).unwrap(); + let section_address = address - section.address; + let data = §ion.data[section_address..] + .iter() + .cloned() + .take_while(|n| *n != 0) + .collect::>(); + + std::str::from_utf8(&data).unwrap().to_string() + } + + fn read_wstring(ctx: &ResolveContext, address: usize) -> String { + let section = ctx.memory.get_section_containing(address).unwrap(); + let section_address = address - section.address; + let data = §ion.data[section_address..] + .chunks(2) + .map(|chunk| ((chunk[1] as u16) << 8) + chunk[0] as u16) + .take_while(|n| *n != 0) + .collect::>(); + + String::from_utf16(&data).unwrap() + } + + #[derive(Debug)] + struct Property { + offset: usize, + name: String, + } + + #[derive(Debug)] + struct Function { + address: usize, + name: String, + } + + pub fn resolve(ctx: ResolveContext, _stages: &mut ResolveStages) -> ResolutionAction { + let package_name_address = + RIPRelativeResolvers::calc_rip(&ctx, ctx.match_address + 9).unwrap(); + let package = read_wstring(&ctx, package_name_address); + let name_address = + RIPRelativeResolvers::calc_rip(&ctx, ctx.match_address + 9 + 4 + 8).unwrap(); + let name = read_wstring(&ctx, name_address); + + let constructor = Pattern::new( + r"48 83 ec 28 + 48 8b ?? [ ?? ?? ?? ?? ] + 48 85 c0 + 75 1a + 48 8d ?? [ ?? ?? ?? ?? ] + 48 8d ?? [ ?? ?? ?? ?? ] + e8 [ ?? ?? ?? ?? ] + 48 8b ?? [ ?? ?? ?? ?? ] + 48 83 c4 28", + ) + .unwrap(); + + let struct_fclass_params = Pattern::new( + r"[ ?? ?? ?? ?? ?? ?? ?? ?? ] + [ ?? ?? ?? ?? ?? ?? ?? ?? ] + [ ?? ?? ?? ?? ?? ?? ?? ?? ] + [ ?? ?? ?? ?? ?? ?? ?? ?? ] + [ ?? ?? ?? ?? ?? ?? ?? ?? ] + [ ?? ?? ?? ?? ?? ?? ?? ?? ] + [ ?? ?? ?? ?? ?? ?? ?? ?? ] + [ ?? ?? ?? ?? ] + [ ?? ?? ?? ?? ] + [ ?? ?? ?? ?? ] + [ ?? ?? ?? ?? ] + [ ?? ?? ?? ?? ]", + ) + .unwrap(); + + let constructor_addr = + RIPRelativeResolvers::calc_rip(&ctx, ctx.match_address + 40).unwrap(); + let constructor_section = ctx.memory.get_section_containing(constructor_addr).unwrap(); + let is_constructor = constructor.captures( + constructor_section.data, + constructor_section.address, + constructor_addr - constructor_section.address, + ); + + let data = if let Some([a, fclass_params, c, d, e]) = is_constructor.as_deref() { + let fclass_params = fclass_params.rip(); + let section = ctx.memory.get_section_containing(fclass_params).unwrap(); + let captures = struct_fclass_params.captures( + section.data, + section.address, + fclass_params - section.address, + ); + let Some( + [ClassNoRegisterFunc, ClassConfigNameUTF8, CppClassInfo, DependencySingletonFuncArray, FunctionLinkArray, PropertyArray, ImplementedInterfaceArray, NumDependencySingletons, NumFunctions, NumProperties, NumImplementedInterfaces, ClassFlags], + ) = captures.as_deref() + else { + unreachable!() + }; + + let mut class_no_register_func_address = ClassNoRegisterFunc.ptr(); + let section = ctx + .memory + .get_section_containing(class_no_register_func_address) + .unwrap(); + + use std::fmt::Write; + let mut hist = String::new(); + let jmps = [ + Pattern::new("e9 [ ?? ?? ?? ?? ]").unwrap(), + Pattern::new("48 83 EC 28 E8 [ ?? ?? ?? ?? ] 48 83 C4 28 C3").unwrap(), + ]; + + let jmp = jmps.iter().find_map(|p| { + p.captures( + section.data, + section.address, + class_no_register_func_address - section.address, + ) + }); + if let Some([address]) = jmp.as_deref() { + writeln!( + hist, + "jumped to {:10X} from {:10X}", + address.rip(), + class_no_register_func_address + ) + .unwrap(); + class_no_register_func_address = address.rip(); + } + + let section = ctx + .memory + .get_section_containing(class_no_register_func_address) + .unwrap(); + let patterns = [ + pattern_static_class(), + pattern_static_class2(), + pattern_static_class3(), + pattern_static_class4(), + ]; + let m = patterns.iter().enumerate().find_map(|(i, p)| { + p.captures( + section.data, + section.address, + class_no_register_func_address - section.address, + ) + .and_then(|m| Some((i, m))) + }); + + if let Some((i, m)) = m { + println!("{i} {:10X}", class_no_register_func_address); + let name = read_wstring(&ctx, m[1].rip()); + let package_name = read_wstring(&ctx, m[2].rip()); + println!("{package_name:?} {name:?} {:10X}", m[0].rip()); + //let package_name = read_wstring(&ctx, static_class[1].rip()); + //println!("{} {}", package_name, name); + } else { + panic!( + "does not match {:10X}\n{hist}", + class_no_register_func_address + ); + } + + let function_link_array = FunctionLinkArray.ptr(); + let property_array = PropertyArray.ptr(); + let num_functions = u32::from_le_bytes(NumFunctions.data.try_into().unwrap()) as usize; + let num_properties = + u32::from_le_bytes(NumProperties.data.try_into().unwrap()) as usize; + let functions = if function_link_array != 0 { + ctx.memory[function_link_array..function_link_array + 0x10 * num_functions] + .chunks(0x10) + .map(|chunk| Function { + address: usize::from_le_bytes(chunk[0..8].try_into().unwrap()), + name: read_string( + &ctx, + usize::from_le_bytes(chunk[8..16].try_into().unwrap()), + ), + }) + .collect() + } else { + vec![] + }; + + let properties = if property_array != 0 { + ctx.memory[property_array..property_array + 8 * num_properties] + .chunks(8) + .map(|chunk| { + let ptr = usize::from_le_bytes(chunk[0..8].try_into().unwrap()); + let bytes = &ctx.memory[ptr..ptr + 8]; + + let name = + read_string(&ctx, usize::from_le_bytes(bytes.try_into().unwrap())); + + let offset = u32::from_le_bytes( + ctx.memory[ptr + 0x24..ptr + 0x28].try_into().unwrap(), + ) as usize; + Property { offset, name } + }) + .collect() + } else { + vec![] + }; + + Some((function_link_array, num_functions, functions, properties)) + } else { + None + }; + + /* + println!("{:x} {} {}", ctx.match_address, package, name); + if let Some((_, _, functions, properties)) = &data { + for function in functions { + println!("\t{:x?}", function); + } + for prop in properties { + println!("\t{:x?}", prop); + } + } + */ + + format!( + "{} {:x} {:x?} {} {}", + is_constructor.is_some(), + ctx.match_address, + data, + package, + name + ) + .into() + /* + format!( + "{:x?}", + §ion.data[section_address..section_address + 10] + ) + .into() + */ + //format!("{}", RIPRelativeResolvers::calc_rip(&ctx, ctx.match_address + 9).unwrap()).into() + //ctx.match_address + 9 + //ResolutionAction::Finish("".to_string().into()) + } + + trait Addressable { + fn rip(&self) -> usize; + fn ptr(&self) -> usize; + } + impl Addressable for patternsleuth_scanner::Capture<'_> { + fn rip(&self) -> usize { + (self.address + 4) + .checked_add_signed(i32::from_le_bytes(self.data.try_into().unwrap()) as isize) + .unwrap() + } + fn ptr(&self) -> usize { + usize::from_le_bytes(self.data.try_into().unwrap()) + } + } + + pub fn resolve_static_class( + ctx: ResolveContext, + _stages: &mut ResolveStages, + ) -> ResolutionAction { + //let package = read_wstring(&ctx, 9); + //let name = read_wstring(&ctx, 9 + 4 + 8); + let section = ctx + .memory + .get_section_containing(ctx.match_address) + .unwrap(); + let captures = pattern_static_class() + .captures( + section.data, + section.address, + ctx.match_address - section.address, + ) + .unwrap(); + + let name = read_wstring(&ctx, captures[0].rip()); + let package_name = read_wstring(&ctx, captures[1].rip()); + format!("{} {}", package_name, name).into() + } +} diff --git a/patternsleuth_scanner/src/lib.rs b/patternsleuth_scanner/src/lib.rs index efa18cf..c12ff34 100644 --- a/patternsleuth_scanner/src/lib.rs +++ b/patternsleuth_scanner/src/lib.rs @@ -84,12 +84,8 @@ impl Pattern { let mut i = 0; for w in s.split_whitespace() { if let Some((s, m)) = Self::parse_hex(w).or_else(|| Self::parse_bits(w)) { - if m != 0xff && sig.is_empty() { - bail!("first byte cannot be \"??\""); - } else { - sig.push(s); - mask.push(m); - } + sig.push(s); + mask.push(m); i += 1; } else { match w { From 524ea15d1c7c1a3f8a69eb26a0df6b9d3a1632cb Mon Sep 17 00:00:00 2001 From: Truman Kilen Date: Tue, 29 Aug 2023 18:11:51 -0500 Subject: [PATCH 2/4] Locate native functions --- patternsleuth/src/patterns.rs | 41 ++++++++++++++++++++++++++++++----- 1 file changed, 36 insertions(+), 5 deletions(-) diff --git a/patternsleuth/src/patterns.rs b/patternsleuth/src/patterns.rs index 03236b6..fa48b21 100644 --- a/patternsleuth/src/patterns.rs +++ b/patternsleuth/src/patterns.rs @@ -2163,6 +2163,18 @@ C3 ) .unwrap(); + let register_natives = Pattern::new( + r" +48 83 EC 28 +E8 ?? ?? ?? ?? +41 B8 [ ?? ?? ?? ?? ] +48 8D ?? [ ?? ?? ?? ?? ] +48 8B C8 +48 83 C4 28 +E9" + ) + .unwrap(); + let constructor_addr = RIPRelativeResolvers::calc_rip(&ctx, ctx.match_address + 40).unwrap(); let constructor_section = ctx.memory.get_section_containing(constructor_addr).unwrap(); @@ -2239,9 +2251,23 @@ C3 if let Some((i, m)) = m { println!("{i} {:10X}", class_no_register_func_address); + let init_address = m[0].rip(); let name = read_wstring(&ctx, m[1].rip()); let package_name = read_wstring(&ctx, m[2].rip()); - println!("{package_name:?} {name:?} {:10X}", m[0].rip()); + println!("{package_name:?} {name:?} {:10X}", init_address); + + let section = ctx + .memory + .get_section_containing(init_address) + .unwrap(); + let captures = register_natives.captures( + section.data, + section.address, + init_address - section.address, + ); + if let Some([count, native_functions]) = captures.as_deref() { + println!("native functions = {:10X?} ({})", native_functions.rip(), count.u32()); + } //let package_name = read_wstring(&ctx, static_class[1].rip()); //println!("{} {}", package_name, name); } else { @@ -2253,9 +2279,8 @@ C3 let function_link_array = FunctionLinkArray.ptr(); let property_array = PropertyArray.ptr(); - let num_functions = u32::from_le_bytes(NumFunctions.data.try_into().unwrap()) as usize; - let num_properties = - u32::from_le_bytes(NumProperties.data.try_into().unwrap()) as usize; + let num_functions = NumFunctions.u32() as usize; + let num_properties = NumProperties.u32() as usize; let functions = if function_link_array != 0 { ctx.memory[function_link_array..function_link_array + 0x10 * num_functions] .chunks(0x10) @@ -2308,6 +2333,7 @@ C3 } */ + /* format!( "{} {:x} {:x?} {} {}", is_constructor.is_some(), @@ -2316,7 +2342,8 @@ C3 package, name ) - .into() + .into();*/ + ResolutionAction::Finish(ResolutionType::Count) /* format!( "{:x?}", @@ -2332,6 +2359,7 @@ C3 trait Addressable { fn rip(&self) -> usize; fn ptr(&self) -> usize; + fn u32(&self) -> u32; } impl Addressable for patternsleuth_scanner::Capture<'_> { fn rip(&self) -> usize { @@ -2342,6 +2370,9 @@ C3 fn ptr(&self) -> usize { usize::from_le_bytes(self.data.try_into().unwrap()) } + fn u32(&self) -> u32 { + u32::from_le_bytes(self.data.try_into().unwrap()) + } } pub fn resolve_static_class( From ddd5508d2efe9af2e79dc6b906fa6f5e9c619f95 Mon Sep 17 00:00:00 2001 From: Truman Kilen Date: Tue, 29 Aug 2023 18:44:08 -0500 Subject: [PATCH 3/4] clean up --- patternsleuth/src/patterns.rs | 166 ++++++++++++++++++---------------- 1 file changed, 89 insertions(+), 77 deletions(-) diff --git a/patternsleuth/src/patterns.rs b/patternsleuth/src/patterns.rs index fa48b21..e96f5d6 100644 --- a/patternsleuth/src/patterns.rs +++ b/patternsleuth/src/patterns.rs @@ -1481,7 +1481,7 @@ pub fn get_patterns() -> Result> { Sig::ClassInitializers, "ClassInitializers".to_string(), None, - Pattern::new("48 83 EC 48 33 C0 4C 8D ?? ?? ?? ?? ?? 48 89 44 24 30 4C 8D ?? ?? ?? ?? ?? 48 89 44 24 28 48 8D ?? ?? ?? ?? ?? 48 8D ?? ?? ?? ?? ?? 88 44 24 20 E8 ?? ?? ?? ?? 48 83 C4 48 C3")?, + class_initializers::pattern_class_initializer().clone(), class_initializers::resolve, ), PatternConfig::new( @@ -1918,11 +1918,31 @@ mod signing_key { } mod class_initializers { - use std::{io::BufRead, sync::OnceLock}; + use std::sync::OnceLock; use super::*; - use byteorder::{ReadBytesExt, LE}; + pub fn pattern_class_initializer() -> &'static Pattern { + static PATTERN: OnceLock = OnceLock::new(); + PATTERN.get_or_init(|| { + Pattern::new( + r#" +48 83 EC 48 +33 C0 +4C 8D ?? [ ?? ?? ?? ?? ] +48 89 44 24 30 +4C 8D ?? [ ?? ?? ?? ?? ] +48 89 44 24 28 +48 8D ?? ?? ?? ?? ?? +48 8D ?? [ ?? ?? ?? ?? ] +88 44 24 20 +E8 ?? ?? ?? ?? +48 83 C4 48 +C3"#, + ) + .unwrap() + }) + } pub fn pattern_static_class() -> &'static Pattern { static PATTERN: OnceLock = OnceLock::new(); @@ -2099,7 +2119,7 @@ C3 .take_while(|n| *n != 0) .collect::>(); - std::str::from_utf8(&data).unwrap().to_string() + std::str::from_utf8(data).unwrap().to_string() } fn read_wstring(ctx: &ResolveContext, address: usize) -> String { @@ -2111,7 +2131,7 @@ C3 .take_while(|n| *n != 0) .collect::>(); - String::from_utf16(&data).unwrap() + String::from_utf16(data).unwrap() } #[derive(Debug)] @@ -2127,15 +2147,9 @@ C3 } pub fn resolve(ctx: ResolveContext, _stages: &mut ResolveStages) -> ResolutionAction { - let package_name_address = - RIPRelativeResolvers::calc_rip(&ctx, ctx.match_address + 9).unwrap(); - let package = read_wstring(&ctx, package_name_address); - let name_address = - RIPRelativeResolvers::calc_rip(&ctx, ctx.match_address + 9 + 4 + 8).unwrap(); - let name = read_wstring(&ctx, name_address); - - let constructor = Pattern::new( - r"48 83 ec 28 + let pattern_constructor = Pattern::new( + r" + 48 83 ec 28 48 8b ?? [ ?? ?? ?? ?? ] 48 85 c0 75 1a @@ -2148,7 +2162,8 @@ C3 .unwrap(); let struct_fclass_params = Pattern::new( - r"[ ?? ?? ?? ?? ?? ?? ?? ?? ] + r" + [ ?? ?? ?? ?? ?? ?? ?? ?? ] [ ?? ?? ?? ?? ?? ?? ?? ?? ] [ ?? ?? ?? ?? ?? ?? ?? ?? ] [ ?? ?? ?? ?? ?? ?? ?? ?? ] @@ -2165,45 +2180,39 @@ C3 let register_natives = Pattern::new( r" -48 83 EC 28 -E8 ?? ?? ?? ?? -41 B8 [ ?? ?? ?? ?? ] -48 8D ?? [ ?? ?? ?? ?? ] -48 8B C8 -48 83 C4 28 -E9" + 48 83 EC 28 + E8 ?? ?? ?? ?? + 41 B8 [ ?? ?? ?? ?? ] + 48 8D ?? [ ?? ?? ?? ?? ] + 48 8B C8 + 48 83 C4 28 + E9", ) .unwrap(); - let constructor_addr = - RIPRelativeResolvers::calc_rip(&ctx, ctx.match_address + 40).unwrap(); - let constructor_section = ctx.memory.get_section_containing(constructor_addr).unwrap(); - let is_constructor = constructor.captures( - constructor_section.data, - constructor_section.address, - constructor_addr - constructor_section.address, - ); + let [package_name, name, constructor] = &ctx + .memory + .captures(pattern_class_initializer(), ctx.match_address) + .unwrap() + .try_into() + .unwrap(); + + let package = read_wstring(&ctx, package_name.rip()); + let name = read_wstring(&ctx, name.rip()); + + let is_constructor = ctx.memory.captures(&pattern_constructor, constructor.rip()); - let data = if let Some([a, fclass_params, c, d, e]) = is_constructor.as_deref() { + let data = if let Some([_a, fclass_params, _c, _d, _e]) = is_constructor.as_deref() { let fclass_params = fclass_params.rip(); - let section = ctx.memory.get_section_containing(fclass_params).unwrap(); - let captures = struct_fclass_params.captures( - section.data, - section.address, - fclass_params - section.address, - ); + let captures = ctx.memory.captures(&struct_fclass_params, fclass_params); let Some( - [ClassNoRegisterFunc, ClassConfigNameUTF8, CppClassInfo, DependencySingletonFuncArray, FunctionLinkArray, PropertyArray, ImplementedInterfaceArray, NumDependencySingletons, NumFunctions, NumProperties, NumImplementedInterfaces, ClassFlags], + [class_no_register_func, _class_config_name_utf8, _cpp_class_info, _dependency_singleton_func_array, function_link_array, property_array, _implemented_interface_array, _num_dependency_singletons, num_functions, num_properties, _num_implemented_interfaces, _class_flags], ) = captures.as_deref() else { unreachable!() }; - let mut class_no_register_func_address = ClassNoRegisterFunc.ptr(); - let section = ctx - .memory - .get_section_containing(class_no_register_func_address) - .unwrap(); + let mut class_no_register_func_address = class_no_register_func.ptr(); use std::fmt::Write; let mut hist = String::new(); @@ -2212,13 +2221,9 @@ E9" Pattern::new("48 83 EC 28 E8 [ ?? ?? ?? ?? ] 48 83 C4 28 C3").unwrap(), ]; - let jmp = jmps.iter().find_map(|p| { - p.captures( - section.data, - section.address, - class_no_register_func_address - section.address, - ) - }); + let jmp = jmps + .iter() + .find_map(|p| ctx.memory.captures(p, class_no_register_func_address)); if let Some([address]) = jmp.as_deref() { writeln!( hist, @@ -2230,10 +2235,6 @@ E9" class_no_register_func_address = address.rip(); } - let section = ctx - .memory - .get_section_containing(class_no_register_func_address) - .unwrap(); let patterns = [ pattern_static_class(), pattern_static_class2(), @@ -2241,12 +2242,9 @@ E9" pattern_static_class4(), ]; let m = patterns.iter().enumerate().find_map(|(i, p)| { - p.captures( - section.data, - section.address, - class_no_register_func_address - section.address, - ) - .and_then(|m| Some((i, m))) + ctx.memory + .captures(p, class_no_register_func_address) + .map(|m| (i, m)) }); if let Some((i, m)) = m { @@ -2256,17 +2254,13 @@ E9" let package_name = read_wstring(&ctx, m[2].rip()); println!("{package_name:?} {name:?} {:10X}", init_address); - let section = ctx - .memory - .get_section_containing(init_address) - .unwrap(); - let captures = register_natives.captures( - section.data, - section.address, - init_address - section.address, - ); + let captures = ctx.memory.captures(®ister_natives, init_address); if let Some([count, native_functions]) = captures.as_deref() { - println!("native functions = {:10X?} ({})", native_functions.rip(), count.u32()); + println!( + "native functions = {:10X?} ({})", + native_functions.rip(), + count.u32() + ); } //let package_name = read_wstring(&ctx, static_class[1].rip()); //println!("{} {}", package_name, name); @@ -2277,10 +2271,10 @@ E9" ); } - let function_link_array = FunctionLinkArray.ptr(); - let property_array = PropertyArray.ptr(); - let num_functions = NumFunctions.u32() as usize; - let num_properties = NumProperties.u32() as usize; + let function_link_array = function_link_array.ptr(); + let property_array = property_array.ptr(); + let num_functions = num_functions.u32() as usize; + let num_properties = num_properties.u32() as usize; let functions = if function_link_array != 0 { ctx.memory[function_link_array..function_link_array + 0x10 * num_functions] .chunks(0x10) @@ -2333,7 +2327,6 @@ E9" } */ - /* format!( "{} {:x} {:x?} {} {}", is_constructor.is_some(), @@ -2342,8 +2335,8 @@ E9" package, name ) - .into();*/ - ResolutionAction::Finish(ResolutionType::Count) + .into() + //ResolutionAction::Finish(ResolutionType::Count) /* format!( "{:x?}", @@ -2375,6 +2368,25 @@ E9" } } + trait Matchable<'data> { + fn captures( + &'data self, + pattern: &Pattern, + address: usize, + ) -> Option>>; + } + + impl<'data> Matchable<'data> for MountedPE<'data> { + fn captures( + &'data self, + pattern: &Pattern, + address: usize, + ) -> Option>> { + self.get_section_containing(address) + .and_then(move |s| pattern.captures(s.data, s.address, address - s.address)) + } + } + pub fn resolve_static_class( ctx: ResolveContext, _stages: &mut ResolveStages, From c1d4705ceb8a0a801f7c5255a5d76cea45486c6e Mon Sep 17 00:00:00 2001 From: Truman Kilen Date: Tue, 29 Aug 2023 19:05:32 -0500 Subject: [PATCH 4/4] asdf --- patternsleuth/src/patterns.rs | 319 +++++++++++++++++----------------- 1 file changed, 157 insertions(+), 162 deletions(-) diff --git a/patternsleuth/src/patterns.rs b/patternsleuth/src/patterns.rs index e96f5d6..41cdc59 100644 --- a/patternsleuth/src/patterns.rs +++ b/patternsleuth/src/patterns.rs @@ -1926,19 +1926,20 @@ mod class_initializers { static PATTERN: OnceLock = OnceLock::new(); PATTERN.get_or_init(|| { Pattern::new( - r#" -48 83 EC 48 -33 C0 -4C 8D ?? [ ?? ?? ?? ?? ] -48 89 44 24 30 -4C 8D ?? [ ?? ?? ?? ?? ] -48 89 44 24 28 -48 8D ?? ?? ?? ?? ?? -48 8D ?? [ ?? ?? ?? ?? ] -88 44 24 20 -E8 ?? ?? ?? ?? -48 83 C4 48 -C3"#, + r" + 48 83 EC 48 + 33 C0 + 4C 8D ?? [ ?? ?? ?? ?? ] + 48 89 44 24 30 + 4C 8D ?? [ ?? ?? ?? ?? ] + 48 89 44 24 28 + 48 8D ?? ?? ?? ?? ?? + 48 8D ?? [ ?? ?? ?? ?? ] + 88 44 24 20 + E8 ?? ?? ?? ?? + 48 83 C4 48 + C3 + ", ) .unwrap() }) @@ -1948,39 +1949,40 @@ C3"#, static PATTERN: OnceLock = OnceLock::new(); PATTERN.get_or_init(|| { Pattern::new( - r#" -4C 8B DC -48 81 EC 88 00 00 00 -48 8B ?? ?? ?? ?? ?? -48 85 C0 -0F 85 ?? ?? ?? ?? -33 C9 -48 8D ?? ?? ?? ?? ?? -49 89 4B F0 -4C 8D ?? [ ?? ?? ?? ?? ] -88 4C 24 70 -4C 8D ?? ?? ?? ?? ?? -49 89 43 E0 -48 8D ?? [ ?? ?? ?? ?? ] -48 8D ?? ?? ?? ?? ?? -49 89 43 D8 -48 8D ?? ?? ?? ?? ?? -49 89 43 D0 -48 8D ?? ?? ?? ?? ?? -49 89 43 C8 -48 8D ?? ?? ?? ?? ?? -49 89 43 C0 -48 8D ?? ?? ?? ?? ?? -49 89 43 B8 -49 89 4B B0 -48 8D ?? [ ?? ?? ?? ?? ] -C7 44 24 30 [ ?? ?? ?? ?? ] -C7 44 24 28 [ ?? ?? ?? ?? ] -C7 44 24 20 [ ?? ?? ?? ?? ] -E8 ?? ?? ?? ?? -48 8B ?? ?? ?? ?? ?? -48 81 C4 88 00 00 00 -C3"#, + r" + 4C 8B DC + 48 81 EC 88 00 00 00 + 48 8B ?? ?? ?? ?? ?? + 48 85 C0 + 0F 85 ?? ?? ?? ?? + 33 C9 + 48 8D ?? ?? ?? ?? ?? + 49 89 4B F0 + 4C 8D ?? [ ?? ?? ?? ?? ] + 88 4C 24 70 + 4C 8D ?? ?? ?? ?? ?? + 49 89 43 E0 + 48 8D ?? [ ?? ?? ?? ?? ] + 48 8D ?? ?? ?? ?? ?? + 49 89 43 D8 + 48 8D ?? ?? ?? ?? ?? + 49 89 43 D0 + 48 8D ?? ?? ?? ?? ?? + 49 89 43 C8 + 48 8D ?? ?? ?? ?? ?? + 49 89 43 C0 + 48 8D ?? ?? ?? ?? ?? + 49 89 43 B8 + 49 89 4B B0 + 48 8D ?? [ ?? ?? ?? ?? ] + C7 44 24 30 [ ?? ?? ?? ?? ] + C7 44 24 28 [ ?? ?? ?? ?? ] + C7 44 24 20 [ ?? ?? ?? ?? ] + E8 ?? ?? ?? ?? + 48 8B ?? ?? ?? ?? ?? + 48 81 C4 88 00 00 00 + C3 + ", ) .unwrap() }) @@ -1990,39 +1992,39 @@ C3"#, static PATTERN: OnceLock = OnceLock::new(); PATTERN.get_or_init(|| { Pattern::new( - r#" -4C 8B DC -48 81 EC 88 00 00 00 -48 8B ?? ?? ?? ?? ?? -48 85 C0 -0F 85 ?? ?? ?? ?? -33 C9 -48 8D ?? ?? ?? ?? ?? -49 89 4B F0 -4C 8D ?? [ ?? ?? ?? ?? ] -88 4C 24 70 -4C 8D ?? ?? ?? ?? ?? -49 89 43 E0 -48 8D ?? [ ?? ?? ?? ?? ] -49 89 43 D8 -48 8D ?? ?? ?? ?? ?? -49 89 43 D0 -48 8D ?? ?? ?? ?? ?? -49 89 43 C8 -48 8D ?? ?? ?? ?? ?? -49 89 43 C0 -48 8D ?? ?? ?? ?? ?? -49 89 43 B8 -49 89 4B B0 -48 8D ?? [ ?? ?? ?? ?? ] -C7 44 24 30 ?? ?? ?? ?? -C7 44 24 28 ?? ?? ?? ?? -C7 44 24 20 ?? ?? ?? ?? -E8 ?? ?? ?? ?? -48 8B ?? ?? ?? ?? ?? -48 81 C4 88 00 00 00 -C3 -"#, + r" + 4C 8B DC + 48 81 EC 88 00 00 00 + 48 8B ?? ?? ?? ?? ?? + 48 85 C0 + 0F 85 ?? ?? ?? ?? + 33 C9 + 48 8D ?? ?? ?? ?? ?? + 49 89 4B F0 + 4C 8D ?? [ ?? ?? ?? ?? ] + 88 4C 24 70 + 4C 8D ?? ?? ?? ?? ?? + 49 89 43 E0 + 48 8D ?? [ ?? ?? ?? ?? ] + 49 89 43 D8 + 48 8D ?? ?? ?? ?? ?? + 49 89 43 D0 + 48 8D ?? ?? ?? ?? ?? + 49 89 43 C8 + 48 8D ?? ?? ?? ?? ?? + 49 89 43 C0 + 48 8D ?? ?? ?? ?? ?? + 49 89 43 B8 + 49 89 4B B0 + 48 8D ?? [ ?? ?? ?? ?? ] + C7 44 24 30 ?? ?? ?? ?? + C7 44 24 28 ?? ?? ?? ?? + C7 44 24 20 ?? ?? ?? ?? + E8 ?? ?? ?? ?? + 48 8B ?? ?? ?? ?? ?? + 48 81 C4 88 00 00 00 + C3 + ", ) .unwrap() }) @@ -2031,38 +2033,39 @@ C3 static PATTERN: OnceLock = OnceLock::new(); PATTERN.get_or_init(|| { Pattern::new( - r#" -4C 8B DC -48 81 EC 88 00 00 00 -48 8B ?? ?? ?? ?? ?? -48 85 C0 -0F 85 ?? ?? ?? ?? -49 89 43 F0 -4C 8D ?? [ ?? ?? ?? ?? ] -88 44 24 70 -4C 8D ?? ?? ?? ?? ?? -48 8D ?? ?? ?? ?? ?? -49 89 43 E0 -48 8D ?? [ ?? ?? ?? ?? ] -49 89 43 D8 -48 8D ?? [ ?? ?? ?? ?? ] -48 8D ?? ?? ?? ?? ?? -49 89 43 D0 -48 8D ?? ?? ?? ?? ?? -49 89 43 C8 -48 8D ?? ?? ?? ?? ?? -49 89 43 C0 -48 8D ?? ?? ?? ?? ?? -49 89 43 B8 -48 B8 ?? ?? ?? ?? ?? ?? ?? ?? -49 89 43 B0 -C7 44 24 30 [ ?? ?? ?? ?? ] -C7 44 24 28 [ ?? ?? ?? ?? ] -C7 44 24 20 [ ?? ?? ?? ?? ] -E8 ?? ?? ?? ?? -48 8B ?? ?? ?? ?? ?? -48 81 C4 88 00 00 00 -C3"#, + r" + 4C 8B DC + 48 81 EC 88 00 00 00 + 48 8B ?? ?? ?? ?? ?? + 48 85 C0 + 0F 85 ?? ?? ?? ?? + 49 89 43 F0 + 4C 8D ?? [ ?? ?? ?? ?? ] + 88 44 24 70 + 4C 8D ?? ?? ?? ?? ?? + 48 8D ?? ?? ?? ?? ?? + 49 89 43 E0 + 48 8D ?? [ ?? ?? ?? ?? ] + 49 89 43 D8 + 48 8D ?? [ ?? ?? ?? ?? ] + 48 8D ?? ?? ?? ?? ?? + 49 89 43 D0 + 48 8D ?? ?? ?? ?? ?? + 49 89 43 C8 + 48 8D ?? ?? ?? ?? ?? + 49 89 43 C0 + 48 8D ?? ?? ?? ?? ?? + 49 89 43 B8 + 48 B8 ?? ?? ?? ?? ?? ?? ?? ?? + 49 89 43 B0 + C7 44 24 30 [ ?? ?? ?? ?? ] + C7 44 24 28 [ ?? ?? ?? ?? ] + C7 44 24 20 [ ?? ?? ?? ?? ] + E8 ?? ?? ?? ?? + 48 8B ?? ?? ?? ?? ?? + 48 81 C4 88 00 00 00 + C3 + ", ) .unwrap() }) @@ -2071,40 +2074,40 @@ C3"#, static PATTERN: OnceLock = OnceLock::new(); PATTERN.get_or_init(|| { Pattern::new( - r#" -4C 8B DC -48 81 EC 88 00 00 00 -48 8B ?? ?? ?? ?? ?? -48 85 C0 -0F 85 ?? ?? ?? ?? -49 89 43 F0 -4C 8D ?? [ ?? ?? ?? ?? ] -88 44 24 70 -4C 8D ?? ?? ?? ?? ?? -48 8D ?? ?? ?? ?? ?? -49 89 43 E0 -48 8D ?? [ ?? ?? ?? ?? ] -48 8D ?? ?? ?? ?? ?? -49 89 43 D8 -48 8D ?? [ ?? ?? ?? ?? ] -48 8D ?? ?? ?? ?? ?? -49 89 43 D0 -48 8D ?? ?? ?? ?? ?? -49 89 43 C8 -48 8D ?? ?? ?? ?? ?? -49 89 43 C0 -48 8D ?? ?? ?? ?? ?? -49 89 43 B8 -48 B8 ?? ?? ?? ?? ?? ?? ?? ?? -49 89 43 B0 -C7 44 24 30 [ ?? ?? ?? ?? ] -C7 44 24 28 [ ?? ?? ?? ?? ] -C7 44 24 20 [ ?? ?? ?? ?? ] -E8 ?? ?? ?? ?? -48 8B ?? ?? ?? ?? ?? -48 81 C4 88 00 00 00 -C3 -"#, + r" + 4C 8B DC + 48 81 EC 88 00 00 00 + 48 8B ?? ?? ?? ?? ?? + 48 85 C0 + 0F 85 ?? ?? ?? ?? + 49 89 43 F0 + 4C 8D ?? [ ?? ?? ?? ?? ] + 88 44 24 70 + 4C 8D ?? ?? ?? ?? ?? + 48 8D ?? ?? ?? ?? ?? + 49 89 43 E0 + 48 8D ?? [ ?? ?? ?? ?? ] + 48 8D ?? ?? ?? ?? ?? + 49 89 43 D8 + 48 8D ?? [ ?? ?? ?? ?? ] + 48 8D ?? ?? ?? ?? ?? + 49 89 43 D0 + 48 8D ?? ?? ?? ?? ?? + 49 89 43 C8 + 48 8D ?? ?? ?? ?? ?? + 49 89 43 C0 + 48 8D ?? ?? ?? ?? ?? + 49 89 43 B8 + 48 B8 ?? ?? ?? ?? ?? ?? ?? ?? + 49 89 43 B0 + C7 44 24 30 [ ?? ?? ?? ?? ] + C7 44 24 28 [ ?? ?? ?? ?? ] + C7 44 24 20 [ ?? ?? ?? ?? ] + E8 ?? ?? ?? ?? + 48 8B ?? ?? ?? ?? ?? + 48 81 C4 88 00 00 00 + C3 + ", ) .unwrap() }) @@ -2157,7 +2160,8 @@ C3 48 8d ?? [ ?? ?? ?? ?? ] e8 [ ?? ?? ?? ?? ] 48 8b ?? [ ?? ?? ?? ?? ] - 48 83 c4 28", + 48 83 c4 28 + ", ) .unwrap(); @@ -2174,7 +2178,8 @@ C3 [ ?? ?? ?? ?? ] [ ?? ?? ?? ?? ] [ ?? ?? ?? ?? ] - [ ?? ?? ?? ?? ]", + [ ?? ?? ?? ?? ] + ", ) .unwrap(); @@ -2186,7 +2191,8 @@ C3 48 8D ?? [ ?? ?? ?? ?? ] 48 8B C8 48 83 C4 28 - E9", + E9 + ", ) .unwrap(); @@ -2315,7 +2321,6 @@ C3 None }; - /* println!("{:x} {} {}", ctx.match_address, package, name); if let Some((_, _, functions, properties)) = &data { for function in functions { @@ -2325,8 +2330,8 @@ C3 println!("\t{:x?}", prop); } } - */ + /* format!( "{} {:x} {:x?} {} {}", is_constructor.is_some(), @@ -2335,18 +2340,8 @@ C3 package, name ) - .into() - //ResolutionAction::Finish(ResolutionType::Count) - /* - format!( - "{:x?}", - §ion.data[section_address..section_address + 10] - ) - .into() - */ - //format!("{}", RIPRelativeResolvers::calc_rip(&ctx, ctx.match_address + 9).unwrap()).into() - //ctx.match_address + 9 - //ResolutionAction::Finish("".to_string().into()) + .into()*/ + ResolutionAction::Finish(ResolutionType::Count) } trait Addressable {