Skip to content

Commit

Permalink
fix a lot of bugs
Browse files Browse the repository at this point in the history
Funcion call obfus
  • Loading branch information
maitrecraft1234 authored Oct 12, 2024
2 parents c8a8358 + aac4965 commit d1418c4
Show file tree
Hide file tree
Showing 6 changed files with 109 additions and 20 deletions.
16 changes: 12 additions & 4 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ use std::process::ExitCode;
use clap::{arg, value_parser, ArgAction, ArgMatches, Command, ValueHint};

use obfuscator::Obfuscator;
const AVAILABLE_OBFUSCATION_METHODS: [&str; 6] = ["int", "string", "fn", "bools", "dead", "rm_cmt"];
const AVAILABLE_OBFUSCATION_METHODS: [&str; 7] =
["int", "string", "fn", "bools", "dead", "rm_cmt", "call"];

fn run_obfuscator(mut obfuscator: Obfuscator, matches: ArgMatches) -> obfuscator::Result<()> {
let run_all = !matches.contains_id("set");
Expand All @@ -29,7 +30,14 @@ fn run_obfuscator(mut obfuscator: Obfuscator, matches: ArgMatches) -> obfuscator
obfuscator.obfuscate_strings()?;
}
if run_all || set_options.contains(&&"fn".to_string()) {
obfuscator.obfuscate_functions()?;
if set_options.contains(&&"call".to_string()) {
eprintln!("fn identifier obfuscation was skipped because it is not compatible with call obfuscation");
} else {
obfuscator.obfuscate_functions()?;
}
}
if set_options.contains(&&"call".to_string()) {
obfuscator.obfuscate_function_calls()?;
}
if run_all || set_options.contains(&&"int".to_string()) {
obfuscator.obfuscate_integers()?;
Expand All @@ -46,13 +54,13 @@ fn run_obfuscation(code: String, matches: ArgMatches) -> ExitCode {
let obfuscator = match Obfuscator::new(code) {
Ok(ob) => ob,
Err(err) => {
println!("{err}");
eprintln!("{err}");
return ExitCode::SUCCESS;
}
};

if let Err(err) = run_obfuscator(obfuscator, matches) {
println!("{err}");
eprintln!("{err}");
ExitCode::FAILURE
} else {
ExitCode::SUCCESS
Expand Down
4 changes: 2 additions & 2 deletions src/obfuscator/boolean.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ fn random_args() -> String {

fn obfuctated_boolean(val: &str) -> String {
let val = match val {
"True" => format!("thruthy({})", random_args()),
"False" => format!("falsy({})", random_args()),
"True" => format!("ohe_thruthy({})", random_args()),
"False" => format!("ohe_falsy({})", random_args()),
_ => unreachable!("boolean obfuscation failing most likely due to unparsed tree"),
};
format!(
Expand Down
5 changes: 4 additions & 1 deletion src/obfuscator/dead_code_entry_points.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,11 @@ fn insert_dead_branches(code: &str, attempt: usize) -> String {
let iterations = rng.gen_range(1..(lines / 3) - attempt);
let mut new_code: String = code.to_string();

assert!(iterations > 0);
for _ in 0..iterations {
let line = rng.gen_range(init::OBFUSCATOR_HELPER_FUNCTIONS.lines().count()..lines);
let line_range = init::OBFUSCATOR_HELPER_FUNCTIONS.lines().count()..lines;
assert!(!line_range.is_empty());
let line = rng.gen_range(line_range);

new_code = new_code
.lines()
Expand Down
57 changes: 56 additions & 1 deletion src/obfuscator/functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use super::error::Result;
use super::random_identifiers::rand_str;
use super::Obfuscator;
use super::Shiftable;
use std::ops::Range;
use tree_sitter::{Tree, TreeCursor};

fn get_fn(tree: &Tree, code: &str) -> Vec<String> {
Expand Down Expand Up @@ -30,6 +31,28 @@ fn get_fn(tree: &Tree, code: &str) -> Vec<String> {
v
}

fn get_fn_calls(tree: &Tree) -> Vec<Range<usize>> {
fn go(cursor: &mut TreeCursor, vec: &mut Vec<Range<usize>>) {
let node = cursor.node();
let node_type = node.kind();

if node_type == "call" {
vec.push(cursor.node().byte_range());
}

if cursor.goto_first_child() {
go(cursor, vec);
cursor.goto_parent();
}
while cursor.goto_next_sibling() {
go(cursor, vec);
}
}
let mut v = vec![];
go(&mut tree.walk(), &mut v);
v
}

fn replace_fn(tree: &mut Tree, code: &str, replace: &str, replacement: &str) -> String {
fn go(
cursor: &mut TreeCursor,
Expand Down Expand Up @@ -64,14 +87,46 @@ fn replace_fn(tree: &mut Tree, code: &str, replace: &str, replacement: &str) ->
code
}

fn hide_call(obfuscator: &Obfuscator, call: Range<usize>) -> String {
let old_call = &obfuscator.code[call];
if old_call.starts_with("ohe") || old_call.starts_with("eval") {
return old_call.to_owned();
}
let new_call = format!("ohe_call_function(r'''{old_call}''')");

new_call
}

impl Obfuscator {
pub fn obfuscate_functions(&mut self) -> Result<()> {
self.reparse(ObfuscatorError::Booleans)?;
let fns = get_fn(&self.tree, &self.code);
for e in &fns {
self.code = replace_fn(&mut self.tree, &self.code, e, &rand_str());
self.reparse(ObfuscatorError::Functions(e.clone()))?;
}
Ok(())
}

pub fn obfuscate_function_calls(&mut self) -> Result<()> {
let mut shift = 0;
let calls = get_fn_calls(&self.tree).into_iter().skip(7);
'outer: for (i, call) in calls.clone().enumerate() {
for cn in calls.clone().take(i) {
if cn.end > call.start {
continue 'outer;
}
}
let call = call.shift(shift);
let len = call.len();

let hidden = hide_call(self, call.clone());

shift += hidden.len() as i32 - len as i32;
self.code.replace_range(call, &hidden);
self.reparse(ObfuscatorError::Functions(
"call replace lead to syntactical error".to_string(),
))?;
}
Ok(())
}
}
45 changes: 34 additions & 11 deletions src/obfuscator/init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,50 @@ use super::{error::ObfuscatorError, Obfuscator};
use tree_sitter::Parser;

pub const OBFUSCATOR_HELPER_FUNCTIONS: &str = r#"
def string_decode(string):
def ohe_string_decode(string):
string = list(string)
if string == []:
return str()
for i in range(len(string)):
if ord(string[i]) >= 35 and ord(string[i]) <= 125 and 0:
string[i] = chr(ord(string[i]) - 1)
return ''.join(string)
return "".join(string)
def ohe_call_function(function_call_string):
ohe = lambda: eval(function_call_string, globals(), locals())
try:
return ohe()
except:
pass
import re, ast, builtins
match = re.match(r'(\w+)\((.*)\)$', function_call_string)
if not match:
return ohe()
func_name, args_string = match.groups()
args = []
kwargs = {}
if args_string:
try:
parsed = ast.parse(f"swagy_func({args_string})").body[0].value.args
args = [ast.literal_eval(arg) for arg in parsed if isinstance(arg, ast.Constant)]
kwargs = {kw.arg: ast.literal_eval(kw.value) for kw in parsed if isinstance(kw, ast.keyword)}
except (SyntaxError, ValueError):
raise ValueError("Invalid arguments in function call string")
if func_name in dir(builtins):
ohe_fun = getattr(builtins, func_name)
else:
ohe_fun = globals().get(func_name)
if ohe_fun is None:
return ohe()
return ohe_fun(*args, **kwargs)
import sys
if (gettrace := getattr(sys, 'gettrace')) and gettrace() or 'pdb' in sys.modules or 'debugpy' in sys.modules or 'pydevd' in sys.modules or 'ptvsd' in sys.modules or 'wdb' in sys.modules:
import os;os._exit(0)
def useless(*args, **kwargs):
def ohe_useless(*args, **kwargs):
return
def thruthy(*args, **kwargs):
return useless(args, kwargs) or 1 == int(float("01.0342671"))
def falsy(*args, **kwargs):
return thruthy(args, value="awae", iteration=2) and str(2) == "the_number_two"
def ohe_thruthy(*args, **kwargs):
return ohe_useless(args, kwargs) or 1 == int(float("01.0342671"))
def ohe_falsy(*args, **kwargs):
return ohe_thruthy(args, value="awae", iteration=2) and str(2) == "the_number_two"
"#;

impl Obfuscator {
Expand Down
2 changes: 1 addition & 1 deletion src/obfuscator/strings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ impl Obfuscator {
let str = &self.code
[e.range.start + e.string_start_skip..e.range.end - e.string_end_skip];

let formated = format!("string_decode(f\"{}\")", string_encode(&e, str));
let formated = format!("ohe_string_decode(f\"{}\")", string_encode(&e, str));

let len = e.range.len();
let range = e.range.shift(shift);
Expand Down

0 comments on commit d1418c4

Please sign in to comment.