I am working with Rhino to try to deobfuscate some JavaScript scripts.
I pass them to the interpreter and it executes them. I would like to
print to screen the string passed to the top level function eval each
time it is called.
I tried working with aspects, but unfortunately the libraries I tried
needed an object associated to the method to add the aspects on so to
use them, and eval function is not associated to any object.
Therefore, I couldn't use aspects to do it.
My solution now is using regular expressions for changing eval for
print before executing the scripts so to automate the process.
However, this is not a totally proper solution for me since some
obfuscation techniques use user defined deobfuscating functions that
use the length of JavaScript code, so if I change it it doesn't work.
Does anybody know how could I add aspects to eval, or how to overwrite
it?
Your question isn't specific to Rhino, it's plain Javascript:
eval = (function(eval) {
return function(s) {
print(s);
return eval(s)
}
})(eval);
redefines eval to print before evuating.
Christophe
Thanks for your reply!
However, I tried the solution in Rhino shell and when calling eval it
prints the code, but does not evaluate it. Is there any other way so
to print the code and evaluate it?
Strange: here what I get:
js> eval("2+2")
2+2
4
It is both printed and evaluated. Can you do the exact same test and/or
provide an excerpt of your shell session?
Ok, I understand why it was not working. The example I tried was :
js> eval("2+2")
2+2
4
js> eval("var t=1+1+1+1")
var t=1+1+1+1
js> t
js: "<stdin>", line 11: uncaught JavaScript runtime exception:
ReferenceError: "t" is not defined.
I got the argument printed, but the variable t was not defined when
trying to access it afterwards. But I remembered that eval changes the
scope (am I right??), then it is logical that the variable t does not
exist in the current scope.
If I define the variable t in the Shell, and then use eval and set t
to value 1+1+1+1 then it works, what I get is:
js> var t
js> t=1
1
js> t
1
js> eval("t=1+1+1+1+1")
t=1+1+1+1+1
5
js>t
5
js>
Thanks a lot for your help;)
You're right! I didn't think about this: eval doesn't introduce a new
scope, my "printing eval" does...
If you only need eval to mutate global variables or evaluate an
expression to a value, this "printing eval" will suffice. If not, you'll
need some java.
That is my problem right now, since I am trying your solution in my
program. What I am doing is using rhino to execute JavaScript embedded
in web pages. So, I extract JavaScript between script tags or src
files, and so to execute it in the interpreter I use eval.
But here comes the problem: imagine the JavaScript code I want to
execute is this:
i=3;
eval("i=8")
It containes eval, and since I use eval so to execute the code, then I
have nested evals. So, to try this in the interpreter I write:
js> var i
js> eval("i=3;eval(\"i=8\");")
i=3;eval("i=8");
8
The result is that the parameter is printed, as well as evaluated, but
the problem is that the nested eval function is the native one from
JavaScript. Therefore "i=8"is not printed. What I want is that each
time it is called the argument is printed, regardless the nesting of
eval functions.
My idea was to change Rhino so to change the eval function and add a
printing statement.
Is it feasable?
Thanks a lot!!!!
Yes but not from within the shell. You have to modifiy the sheel or
build your own environment.
For the "printing eval" part: create a java class implementing
org.mozilla.javascript.Callable with the method below:
Object call(Context cx, Scriptable scope, Scriptable thisObj,
java.lang.Object[] args) {
System.out.println(args[0]);
return cx.evaluateString(scope, args[0], "-", 1);
}
And put an instance of it in the global scope under the name "eval".
Thanks! However, a faculty mate already worked with Rhino and proposed
me to add the following method in the Global.java file of the shell:
public static Object eval(Context cx, Scriptable thisObj,Object[]
args, Function funObj)
{
PrintStream out = getInstance(funObj).getOut();
for (int i=0; i < args.length; i++) {
if (i > 0)
out.print(" ");
// Convert the arbitrary JavaScript value into a string form.
String s = Context.toString(args[i]);
out.print(s);
}
out.println();
cx.evaluateString(ScriptableObject.getTopLevelScope(thisObj),
args[0].toString(), "-", 1, null);
return Context.getUndefinedValue();
}
It is a combination of eval function and the print function defined in
the Shell. Besides, I have to add the string "eval" to the array
defined in the public void init(Context cx) method. The array is
called: String[] names
Now when I invoke the Shell this function is executed instead of the
standard one.
Besides, I would like also to change the unescape function, so to add
the same print functionality. Your first suggestion for eval function
seems to be enough for me. In case I need to change it as eval, that
is, modifying the source code, then I will ask you where to find it.
Thank you very much!