rendered paste bodyusing NObfs.Tree;
using NObfs.Dump;
using System;
namespace NObfs {
public module NObfs {
public Main() : void {
def Expr(expr : NExpr) {
| Var(var) => var : object
| Number(num) => num : object
| x => x
}
def FindAssign(tree, var, ass : NExpr = null) : NExpr {
Walk(
tree,
fun(expr : NExpr) {
| Assign(left, right) when (right : object) != ass =>
match(left) {
| Var(var_) when var_ == var =>
right
| _ => null
}
| _ => null
}
) :> NExpr
}
def tree = Dump.DumpTree;
def stateDeobfsVar = Walk(
tree,
fun(expr : NExpr) {
| Switch(expr, _) => Expr(expr)
| _ => null
}
) :> string;
Console.WriteLine(
"Deobfs state == {0}",
stateDeobfsVar
);
def (stateObfsVar, stateOff) = match(FindAssign(tree, stateDeobfsVar)) {
| Arith(type_, left, right) =>
(
Expr(left) :> string,
match(type_) {
| Add => Expr(right) :> long
| Sub => -(Expr(right) :> long)
| _ => throw Exception("WTF?")
}
)
| _ => throw Exception("Uh?")
}
Console.WriteLine(
"Obfs state == {0}",
stateObfsVar
);
Console.WriteLine(
"State offset == {0}",
stateOff
);
def initialState = (Expr(FindAssign(tree, stateObfsVar)) :> long + stateOff) :> uint;
Console.WriteLine(
"Initial state == {0}",
initialState
);
def EvaluateVar(var, ass, stack) {
match(stack) {
| [] =>
def expr = NExpr.Number(-1);
(expr, expr, stack)
| case :: rest =>
def expr = FindAssign(case, var, ass);
if(expr == null)
EvaluateVar(var, ass, rest)
else
(expr, expr, stack)
}
}
def Evaluate(expr : NExpr, ass, stack) {
match(expr) {
| Comp(type_, left, right) =>
def left = Evaluate(left, ass, stack);
def right = Evaluate(right, ass, stack);
if(
match(type_) {
| EQ => left == right
| NE => left != right
| SGE => left >= right
| UGE => left >= right
| SLE => left <= right
| ULE => left <= right
| SGT => left > right
| UGT => left > right
| SLT => left < right
| ULT => left < right
}
)
1
else
0
| Arith(type_, left, right) =>
def left = Evaluate(left, ass, stack);
def right = Evaluate(right, ass, stack);
match(type_) {
| Or => (left | right)
| Xor => left ^ right
| And => left & right
| SShr => left >> right
| UShr => left >> right
| Shl => left << right
| Add => left + right
| Sub => left - right
| Mul => left * right
| SDiv => left / right
| UDiv => left / right
| SMod => left % right
| UMod => left % right
}
| Cast(type_, expr) =>
def value = Evaluate(expr, ass, stack);
def sign = {
if(value >= 0) 1
else -1
};
match(type_) {
| "char" => (value % 128) * sign
| x => throw Exception(String.Format("Unknown cast type '{0}'", x))
}
| Var(var) =>
Evaluate(EvaluateVar(var, ass, stack))
| Number(num) => num :> int
| x => throw Exception(String.Format("Unknown type {0}", x))
}
}
def DefyLogic(state, stack) : void {
def case = Walk(
tree,
fun(expr : NExpr) {
| Case(values, _) when values.Contains(state) => expr
| _ => null
}
) :> NExpr;
def stack = case :: stack;
def stateExpr = FindAssign(case, stateObfsVar);
def nextState = (Evaluate(stateExpr, stateExpr, stack) + stateOff) :> uint;
Console.WriteLine("Next state == {0}", nextState);
unless(nextState == 0U)
DefyLogic(nextState, stack);
}
DefyLogic(initialState, [tree]);
}
Walk(tree : NExpr, func : NExpr -> object) : object {
def WalkList(exprs, func) {
match(exprs) {
| [] => null
| head :: tail =>
def ret = Walk(head, func);
if(ret == null)
WalkList(tail, func)
else
ret
}
}
def ret = func(tree);
if(ret == null) {
match(tree) {
| Loc(_, body)
| Case(_, body)
| While(_, body) => Walk(body, func)
| Switch(_, body)
| Block(body) => WalkList(body, func)
| If(_, then, else_) =>
def ret = Walk(then, func);
if(ret == null)
Walk(else_, func)
else
ret
| _ => null
}
} else
ret
}
WalkAll(tree : NExpr, func : NExpr -> object, mutable accum : list [object] = null) : list [object] {
def WalkList(exprs, func, accum) {
match(exprs) {
| [] => accum
| head :: tail =>
WalkList(
tail,
func,
WalkAll(head, func, accum)
)
}
}
when(accum == null)
accum = [];
def ret = func(tree);
unless(ret == null)
accum = ret :: accum;
match(tree) {
| Loc(_, body)
| Case(_, body)
| While(_, body) => WalkAll(body, func, accum)
| Switch(_, body)
| Block(body) => WalkList(body, func, accum)
| If(_, then, else_) =>
WalkAll(
else_,
func,
WalkAll(
then,
func,
accum
)
)
| _ => accum
}
}
}
}