Skip to content

Commit

Permalink
🚧 shelving
Browse files Browse the repository at this point in the history
  • Loading branch information
ShellWen committed Oct 7, 2023
1 parent e964f1a commit 5d93563
Show file tree
Hide file tree
Showing 8 changed files with 271 additions and 53 deletions.
6 changes: 4 additions & 2 deletions crates/core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@ crate-type = ["cdylib"]
[dependencies]
frida-gum = { version = "0.13.2", features = ["auto-download", "invocation-listener"] }
lazy_static = "1.4.0"
ctor = "0.2.4"
toml = "0.8.1"
ctor = "0.2.5"
toml = "0.8.2"
serde = { version = "1.0.188", features = ["derive"] }
proc-maps = "0.3.2"
aobscan = "0.3.0"

[target.'cfg(target_os = "windows")'.dependencies]
windows = { version = "0.51.1", features = [
Expand Down
17 changes: 17 additions & 0 deletions crates/core/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,21 @@ use serde::Deserialize;
use crate::matcher::SourceMatcher;
use crate::processor::SourceProcessor;

#[derive(Deserialize, Debug)]
pub struct Common {
pub use_export_name: bool,
pub use_sigscan: bool,
}

impl Default for Common {
fn default() -> Self {
Common {
use_export_name: true,
use_sigscan: true,
}
}
}

#[derive(Deserialize, Debug)]
pub struct ConfigRule {
pub matcher: Box<SourceMatcher>,
Expand All @@ -16,6 +31,8 @@ pub struct ConfigRule {

#[derive(Deserialize, Debug)]
pub struct Config {
#[serde(default)]
pub common: Common,
pub rules: HashMap<String, ConfigRule>,
}

Expand Down
2 changes: 1 addition & 1 deletion crates/core/src/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::ops::Deref;

use crate::config::Config;
use crate::source::Source;
use crate::v8_sys::{
use crate::v8_types::{
local_string_from_string, string_from_local_string, v8_context_get_isolate, V8Context, V8Source,
};

Expand Down
38 changes: 13 additions & 25 deletions crates/core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,22 @@ use std::path::Path;

use ctor::ctor;
use frida_gum::interceptor::{InvocationContext, InvocationListener};
use frida_gum::{interceptor::Interceptor, Gum, Module};
use frida_gum::{interceptor::Interceptor, Gum};
use lazy_static::lazy_static;

use crate::config::{Config, FileConfig};
use crate::core::process_script;
use crate::v8_exports::V8_SCRIPT_COMPILER_COMPILE_FUNCTION_INTERNAL_SYMBOL;
use crate::v8_sys::{V8Context, V8Source};
use crate::v8_exports::EXPORTS;
use crate::v8_types::{V8Context, V8Source};

mod config;
mod core;
mod matcher;
mod memory_region;
mod processor;
mod source;
mod v8_exports;
mod v8_sys;
mod v8_types;

lazy_static! {
static ref GUM: Gum = unsafe { Gum::obtain() };
Expand Down Expand Up @@ -72,28 +73,15 @@ fn init() {

interceptor.begin_transaction();

let v8_script_compiler_compile_function_internal = Module::find_export_by_name(
None,
V8_SCRIPT_COMPILER_COMPILE_FUNCTION_INTERNAL_SYMBOL,
);
let v8_script_compiler_compile_function_internal =
EXPORTS.v8_script_compiler_compile_function_internal;

match v8_script_compiler_compile_function_internal {
None => {
println!("[-] v8_script_compiler_compile_function_internal not found")
}
Some(addr) => {
println!(
"[*] v8_script_compiler_compile_function_internal found: {:?}",
addr.0
);
let mut v8_script_compiler_compile_function_internal_listener =
V8ScriptCompilerCompileFunctionInternalListener;
interceptor.attach(
addr,
&mut v8_script_compiler_compile_function_internal_listener,
);
}
}
let mut v8_script_compiler_compile_function_internal_listener =
V8ScriptCompilerCompileFunctionInternalListener;
interceptor.attach(
v8_script_compiler_compile_function_internal,
&mut v8_script_compiler_compile_function_internal_listener,
);

interceptor.end_transaction();
}
Expand Down
39 changes: 39 additions & 0 deletions crates/core/src/memory_region.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
use std::error::Error;

#[derive(Debug)]
pub struct MemoryRegion {
pub start: usize,
pub size: usize,
}

impl MemoryRegion {
pub fn new(start: usize, size: usize, skip_check: bool) -> MemoryRegion {
if !skip_check {
// TODO: Check if the region is valid
}
MemoryRegion { start, size }
}
pub fn to_slice(&self) -> &[u8] {
unsafe { std::slice::from_raw_parts(self.start as *const u8, self.size) }
}
}

impl MemoryRegion {
pub fn from_executable() -> Result<Vec<MemoryRegion>, Box<dyn Error>> {
let current_pid = std::process::id();
let maps = proc_maps::get_process_maps(current_pid as proc_maps::Pid)?;
let primary_module_name = maps.first().unwrap().filename().unwrap().as_os_str();
let ret = maps
.iter()
.filter(|m| {
let filename_osstr = match m.filename() {
Some(filename) => filename.as_os_str(),
None => std::ffi::OsStr::new(""),
};
filename_osstr == primary_module_name && m.is_exec() && m.is_read()
})
.map(|m| MemoryRegion::new(m.start(), m.size(), false))
.collect();
Ok(ret)
}
}
192 changes: 181 additions & 11 deletions crates/core/src/v8_exports.rs
Original file line number Diff line number Diff line change
@@ -1,26 +1,196 @@
use aobscan::PatternBuilder;
use frida_gum::{Module, NativePointer};
use lazy_static::lazy_static;
use std::ffi::c_void;

use crate::memory_region::MemoryRegion;
use crate::CONFIG;

#[cfg(any(target_os = "linux", target_os = "macos"))]
pub const V8_SCRIPT_COMPILER_COMPILE_FUNCTION_INTERNAL_SYMBOL: &str = "_ZN2v814ScriptCompiler23CompileFunctionInternalENS_5LocalINS_7ContextEEEPNS0_6SourceEmPNS1_INS_6StringEEEmPNS1_INS_6ObjectEEENS0_14CompileOptionsENS0_13NoCacheReasonEPNS1_INS_14ScriptOrModuleEEE";
const V8_SCRIPT_COMPILER_COMPILE_FUNCTION_INTERNAL_SYMBOL: &str = "_ZN2v814ScriptCompiler23CompileFunctionInternalENS_5LocalINS_7ContextEEEPNS0_6SourceEmPNS1_INS_6StringEEEmPNS1_INS_6ObjectEEENS0_14CompileOptionsENS0_13NoCacheReasonEPNS1_INS_14ScriptOrModuleEEE";
#[cfg(target_os = "windows")]
pub const V8_SCRIPT_COMPILER_COMPILE_FUNCTION_INTERNAL_SYMBOL: &str = "?CompileFunctionInternal@ScriptCompiler@v8@@CA?AV?$MaybeLocal@VFunction@v8@@@2@V?$Local@VContext@v8@@@2@PEAVSource@12@_KQEAV?$Local@VString@v8@@@2@2QEAV?$Local@VObject@v8@@@2@W4CompileOptions@12@W4NoCacheReason@12@PEAV?$Local@VScriptOrModule@v8@@@2@@Z";
const V8_SCRIPT_COMPILER_COMPILE_FUNCTION_INTERNAL_SYMBOL: &str = "?CompileFunctionInternal@ScriptCompiler@v8@@CA?AV?$MaybeLocal@VFunction@v8@@@2@V?$Local@VContext@v8@@@2@PEAVSource@12@_KQEAV?$Local@VString@v8@@@2@2QEAV?$Local@VObject@v8@@@2@W4CompileOptions@12@W4NoCacheReason@12@PEAV?$Local@VScriptOrModule@v8@@@2@@Z";

#[cfg(any(target_os = "linux", target_os = "macos"))]
pub const V8_STRING_UTF8LENGTH_SYMBOL: &str = "_ZNK2v86String10Utf8LengthEPNS_7IsolateE";
const V8_STRING_UTF8LENGTH_SYMBOL: &str = "_ZNK2v86String10Utf8LengthEPNS_7IsolateE";
#[cfg(target_os = "windows")]
pub const V8_STRING_UTF8LENGTH_SYMBOL: &str = "?Utf8Length@String@v8@@QEBAHPEAVIsolate@2@@Z";
const V8_STRING_UTF8LENGTH_SYMBOL: &str = "?Utf8Length@String@v8@@QEBAHPEAVIsolate@2@@Z";

#[cfg(any(target_os = "linux", target_os = "macos"))]
pub const V8_STRING_WRITE_UTF8_SYMBOL: &str = "_ZNK2v86String9WriteUtf8EPNS_7IsolateEPciPii";
const V8_STRING_WRITE_UTF8_SYMBOL: &str = "_ZNK2v86String9WriteUtf8EPNS_7IsolateEPciPii";
#[cfg(target_os = "windows")]
pub const V8_STRING_WRITE_UTF8_SYMBOL: &str =
"?WriteUtf8@String@v8@@QEBAHPEAVIsolate@2@PEADHPEAHH@Z";
const V8_STRING_WRITE_UTF8_SYMBOL: &str = "?WriteUtf8@String@v8@@QEBAHPEAVIsolate@2@PEADHPEAHH@Z";

#[cfg(any(target_os = "linux", target_os = "macos"))]
pub const V8_CONTEXT_GET_ISOLATE_SYMBOL: &str = "_ZN2v87Context10GetIsolateEv";
const V8_CONTEXT_GET_ISOLATE_SYMBOL: &str = "_ZN2v87Context10GetIsolateEv";
#[cfg(target_os = "windows")]
pub const V8_CONTEXT_GET_ISOLATE_SYMBOL: &str = "?GetIsolate@Context@v8@@QEAAPEAVIsolate@2@XZ";
const V8_CONTEXT_GET_ISOLATE_SYMBOL: &str = "?GetIsolate@Context@v8@@QEAAPEAVIsolate@2@XZ";

#[cfg(any(target_os = "linux", target_os = "macos"))]
pub const V8_STRING_NEW_FROM_UTF8_PTR: &str =
const V8_STRING_NEW_FROM_UTF8_PTR: &str =
"_ZN2v86String11NewFromUtf8EPNS_7IsolateEPKcNS_13NewStringTypeEi";
#[cfg(target_os = "windows")]
pub const V8_STRING_NEW_FROM_UTF8_PTR: &str = "?NewFromUtf8@String@v8@@SA?AV?$MaybeLocal@VString@v8@@@2@PEAVIsolate@2@PEBDW4NewStringType@2@H@Z";
const V8_STRING_NEW_FROM_UTF8_PTR: &str = "?NewFromUtf8@String@v8@@SA?AV?$MaybeLocal@VString@v8@@@2@PEAVIsolate@2@PEBDW4NewStringType@2@H@Z";

pub struct Exports {
pub v8_script_compiler_compile_function_internal: NativePointer,
pub v8_string_utf8_length: NativePointer,
pub v8_string_write_utf8: NativePointer,
pub v8_context_get_isolate: NativePointer,
pub v8_string_new_from_utf8: NativePointer,
}

// Unsafe, but we only use it in static context
unsafe impl Sync for Exports {}

fn find_export_by_name(export_name: &str) -> Option<NativePointer> {
Module::find_export_by_name(None, export_name)
}

fn find_export_by_signature(signature: &str) -> Option<NativePointer> {
let pattern = PatternBuilder::from_ida_style(signature)
.unwrap()
.with_all_threads()
.build();
let mut results = vec![];
MEMORY_REGIONS.iter().for_each(|region| {
let slice = region.to_slice();
pattern.scan(&slice, |result| {
results.push(region.start + result);
true
});
});
if results.len() > 0 {
if results.len() > 1 {
println!(
"[!] Found {} results for signature {}, use first",
results.len(),
signature
);
}
Some(NativePointer(results[0] as *mut c_void))
} else {
None
}
}

fn find_export(export_name: Option<&str>, signature: Option<&str>) -> Option<NativePointer> {
let export_found_by_name = match export_name {
Some(export_name) => {
println!("[*] Finding export {}...", export_name);
let export = find_export_by_name(export_name);
match export {
Some(export) => {
println!("[+] Found export {} at {:p}", export_name, export.0);
Some(export)
}
None => {
println!("[-] Failed to find export {}", export_name);
None
}
}
}
None => None,
};
if export_found_by_name.is_some() {
return export_found_by_name;
}
let export_found_by_signature = match signature {
Some(signature) => {
println!("[*] Finding export {} by signature...", signature);
let export = find_export_by_signature(signature);
match export {
Some(export) => {
println!(
"[+] Found export {} at {:p} by signature",
signature, export.0
);
Some(export)
}
None => {
println!("[-] Failed to find export {} by signature", signature);
None
}
}
}
None => None,
};
if export_found_by_signature.is_some() {
return export_found_by_signature;
}

None
}

fn find_all_exports() -> Exports {
let config = unsafe { CONFIG.as_ref().unwrap() };
let use_export_name = config.common.use_export_name;
let use_sigscan = config.common.use_sigscan;

let v8_script_compiler_compile_function_internal = find_export(
if use_export_name {
Some(V8_SCRIPT_COMPILER_COMPILE_FUNCTION_INTERNAL_SYMBOL)
} else {
None
},
if use_sigscan { Some("55 48 ?? ?? 41 ?? 41 ?? 41 ?? 49 ?? ?? 41 ?? 53 48 ?? ?? 48 ?? ?? ?? ?? ?? ?? 48 ?? ?? ?? 48 ?? ?? ?? ?? ?? ?? 48 ?? ?? ?? ?? ?? ?? 4c ?? ?? ?? ?? ?? ?? 4c ?? ?? ?? ?? ?? ?? 48 ?? ?? ?? ?? ?? ?? 64") } else { None },
)
.expect("Failed to find v8_script_compiler_compile_function_internal");
let v8_string_utf8_length = find_export(
if use_export_name {
Some(V8_STRING_UTF8LENGTH_SYMBOL)
} else {
None
},
if use_sigscan {
Some("48 8B 07 8B 40 0B C3")
} else {
None
},
)
.expect("Failed to find v8_string_utf8_length");
let v8_string_write_utf8 = find_export(
if use_export_name {
Some(V8_STRING_WRITE_UTF8_SYMBOL)
} else {
None
},
if use_sigscan { Some("55 48 ?? ?? 41 ?? 45 ?? ?? 41 ?? 41 ?? 41 ?? 49 ?? ?? 53 48 ?? ?? 48 ?? ?? ?? ?? ?? ?? 48 ?? ?? ?? ?? ?? ?? 4C ?? ?? ?? ?? ?? ?? 64 ?? ?? ?? ?? ?? ?? ?? ?? 48") } else { None },
)
.expect("Failed to find v8_string_write_utf8");
let v8_context_get_isolate = find_export(
if use_export_name {
Some(V8_CONTEXT_GET_ISOLATE_SYMBOL)
} else {
None
},
if use_sigscan {
Some("48 8B 07 48 25 00 00 FC FF 48 8B 40 10 48 ?? ?? ?? ?? ?? C3")
} else {
None
},
)
.expect("Failed to find v8_context_get_isolate");
let v8_string_new_from_utf8 = find_export(
if use_export_name {
Some(V8_STRING_NEW_FROM_UTF8_PTR)
} else {
None
},
if use_sigscan { Some("55 48 ?? ?? 41 ?? 53 48 ?? ?? 48 ?? ?? ?? 64 ?? ?? ?? ?? ?? ?? ?? ?? 48 ?? ?? ?? 31 ?? 48 ?? ?? ?? ?? ?? ?? 85 ?? 74 ?? 81 ?? ?? ?? ?? ?? 7E ?? 31 ??") } else { None },
)
.expect("Failed to find v8_string_new_from_utf8");

Exports {
v8_script_compiler_compile_function_internal,
v8_string_utf8_length,
v8_string_write_utf8,
v8_context_get_isolate,
v8_string_new_from_utf8,
}
}

lazy_static! {
static ref MEMORY_REGIONS: Vec<MemoryRegion> = MemoryRegion::from_executable().unwrap();
pub static ref EXPORTS: Exports = find_all_exports();
}
Loading

0 comments on commit 5d93563

Please sign in to comment.