All pastes #996012 Raw Edit

Something

public text v1 · immutable
#996012 ·published 2008-04-24 17:38 UTC
rendered paste body
using 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
			}
		}
	}
}