fix: extractor: global variable extraction fixed

This commit is contained in:
ThetaDev 2025-03-26 01:20:35 +01:00
parent 23c8775326
commit ac44e95a88
No known key found for this signature in database
GPG key ID: E319D3C5148D65B6

View file

@ -187,6 +187,7 @@ fn extract_js_fn(js: &str, name: &str) -> Result<String, DeobfError> {
struct Level { struct Level {
brace: isize, brace: isize,
paren: isize, paren: isize,
bracket: isize,
} }
let mut level = Level::default(); let mut level = Level::default();
@ -197,6 +198,7 @@ fn extract_js_fn(js: &str, name: &str) -> Result<String, DeobfError> {
let mut last_ident = None; let mut last_ident = None;
let mut idents: HashMap<String, bool> = HashMap::new(); let mut idents: HashMap<String, bool> = HashMap::new();
// Set if the current statement is a variable/function param definition // Set if the current statement is a variable/function param definition
// First value is the brace level, second is true if we are on the right hand side of an assignment
let mut var_def_stmt: Option<(Level, bool)> = None; let mut var_def_stmt: Option<(Level, bool)> = None;
let global_objects = [ let global_objects = [
@ -258,20 +260,33 @@ fn extract_js_fn(js: &str, name: &str) -> Result<String, DeobfError> {
} }
level.paren -= 1; level.paren -= 1;
} }
Punct::OpenBracket => {
level.bracket += 1;
}
Punct::CloseBracket => {
if var_def_stmt
.as_ref()
.map(|(x, _)| x == &level)
.unwrap_or_default()
{
var_def_stmt = None;
}
level.bracket -= 1;
}
Punct::SemiColon => { Punct::SemiColon => {
var_def_stmt = None; var_def_stmt = None;
} }
Punct::Comma => { Punct::Comma => {
if let Some((lvl, en)) = &mut var_def_stmt { if let Some((lvl, rhs)) = &mut var_def_stmt {
if lvl == &level { if lvl == &level {
*en = false; *rhs = false;
} }
} }
} }
Punct::Equal => { Punct::Equal => {
if let Some((lvl, en)) = &mut var_def_stmt { if let Some((lvl, rhs)) = &mut var_def_stmt {
if lvl == &level { if lvl == &level {
*en = true; *rhs = true;
} }
} }
} }
@ -297,7 +312,7 @@ fn extract_js_fn(js: &str, name: &str) -> Result<String, DeobfError> {
if !period_before && id.as_ref().len() > 1 { if !period_before && id.as_ref().len() > 1 {
if var_def_stmt if var_def_stmt
.as_ref() .as_ref()
.map(|(lvl, en)| lvl == &level && !en) .map(|(lvl, rhs)| lvl == &level && !rhs)
.unwrap_or_default() .unwrap_or_default()
{ {
idents.insert(id.to_string(), true); idents.insert(id.to_string(), true);
@ -670,10 +685,13 @@ c[36](c[8],c[32]),c[20](c[25],c[10]),c[2](c[22],c[8]),c[32](c[20],c[16]),c[32](c
("3bb1f723", "MyOSJXtKI3m-uME_jv7-pT12gOFC02RFkGoqWpzE0Cs69VdbwQ0LDp1v7j8xx92efCJlYFYb1sUkkBSPOlPmXgIARw8JQ0qOAOAA"), ("3bb1f723", "MyOSJXtKI3m-uME_jv7-pT12gOFC02RFkGoqWpzE0Cs69VdbwQ0LDp1v7j8xx92efCJlYFYb1sUkkBSPOlPmXgIARw8JQ0qOAOAA"),
("2f1832d2", "0QJ8wRAIgXmPlOPSBkkUs1bYFYlJCfe29xxAj7v1pDL0QwbdV96sCIEzpWqMGkFR20CFOg51Tp-7vj_EMu-m37KtXJ2OySqa0q"), ("2f1832d2", "0QJ8wRAIgXmPlOPSBkkUs1bYFYlJCfe29xxAj7v1pDL0QwbdV96sCIEzpWqMGkFR20CFOg51Tp-7vj_EMu-m37KtXJ2OySqa0q"),
("643afba4", "AAOAOq0QJ8wRAIgXmPlOPSBkkUs1bYFYlJCfe29xx8j7vgpDL0QwbdV06sCIEzpWqMGkFR20CFOS21Tp-7vj_EMu-m37KtXJoOy1"), ("643afba4", "AAOAOq0QJ8wRAIgXmPlOPSBkkUs1bYFYlJCfe29xx8j7vgpDL0QwbdV06sCIEzpWqMGkFR20CFOS21Tp-7vj_EMu-m37KtXJoOy1"),
("363db69b", "0aqSyOoJXtK73m-uME_jv7-pT15gOFC02RFkGMqWpz2ICs6EVdbwQ0LDp1v7j8xx92efCJlYFYb1sUkkBSPOlPmXgIARw8JQ0qOAOAA"),
]; ];
for (js_hash, exp_sig) in cases { for (js_hash, exp_sig) in cases {
tracing::info!("[{js_hash}] SIG_TEST"); let span = tracing::span!(tracing::Level::ERROR, "sig_test", js_hash);
let _enter = span.enter();
let (js_url, js_path) = player_js_file(js_hash).await; let (js_url, js_path) = player_js_file(js_hash).await;
let player_js = std::fs::read_to_string(js_path).unwrap(); let player_js = std::fs::read_to_string(js_path).unwrap();
let deobf_data = DeobfData::extract_fns(&js_url, &player_js).unwrap(); let deobf_data = DeobfData::extract_fns(&js_url, &player_js).unwrap();
@ -724,17 +742,19 @@ c[36](c[8],c[32]),c[20](c[25],c[10]),c[2](c[22],c[8]),c[32](c[20],c[16]),c[32](c
("074a8365", "Ha7507LzRmH3Utygtj", "ufTsrE0IVYrkl8v"), ("074a8365", "Ha7507LzRmH3Utygtj", "ufTsrE0IVYrkl8v"),
("643afba4", "N5uAlLqm0eg1GyHO", "dCBQOejdq5s-ww"), ("643afba4", "N5uAlLqm0eg1GyHO", "dCBQOejdq5s-ww"),
("69f581a5", "-qIP447rVlTTwaZjY", "KNcGOksBAvwqQg"), ("69f581a5", "-qIP447rVlTTwaZjY", "KNcGOksBAvwqQg"),
("643afba4", "ir9-V6cdbCiyKxhr", "2PL7ZDYAALMfmA"), ("363db69b", "eWYu5d5YeY_4LyEDc", "XJQqf-N7Xra3gg"),
]; ];
for (js_hash, nsig_in, exp_nsig) in cases { for (js_hash, nsig_in, exp_nsig) in cases {
tracing::info!("[{js_hash}] NSIG_TEST"); let span = tracing::span!(tracing::Level::ERROR, "nsig_test", js_hash);
let _enter = span.enter();
let (js_url, js_path) = player_js_file(js_hash).await; let (js_url, js_path) = player_js_file(js_hash).await;
let player_js = std::fs::read_to_string(js_path).unwrap(); let player_js = std::fs::read_to_string(js_path).unwrap();
let deobf_data = DeobfData::extract_fns(&js_url, &player_js).unwrap(); let deobf_data = DeobfData::extract_fns(&js_url, &player_js).expect(js_hash);
let deobf = Deobfuscator::new(&deobf_data).unwrap(); let deobf = Deobfuscator::new(&deobf_data).expect(js_hash);
let deobf_nsig = deobf.deobfuscate_nsig(nsig_in).unwrap(); let deobf_nsig = deobf.deobfuscate_nsig(nsig_in).expect(js_hash);
assert_eq!(deobf_nsig, exp_nsig, "[{js_hash}]"); assert_eq!(deobf_nsig, exp_nsig, "[{js_hash}]");
} }
} }