Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

JavaScript code mangler / scrambler / ... khm, more than obfuscator... :)

47 views
Skip to first unread message

Andrew

unread,
Dec 22, 2009, 6:04:30 AM12/22/09
to
Hi!

I hope I can get close to Sun and avoid the flames... ;)

First of all, I have read and fully understand numerous postings on
obfuscation. Also, I understand and mostly agree with this:
http://jibbering.com/faq/obfuscate.html
I have also personally successfully decoded JS that was encoded with
http://www.javascript-source.com/, http://www.stunnix.com/ and
http://www.semdesigns.com/Products/LanguageTools/ECMAScriptTools.html.
I haven't even checked the numerous others I have found because they
look even worse. So I know how futile the resistance is. ;)

BUT: I am looking for something that would NOT (only) do the basic
comments stripping / names renaming, but also changed the (apparent,
of course) flow of the program. Sth. that would convert:
-----
sqrt=function(x) {
return(x*x);
}
-----
to sth. like this:
-----
b=function(v) {
return(a(-v));
}
a=function(x) {
if (x<4)
{
a=x+3;
b=x-7;
c=(x%a)+4;
return((b-c)*(b-c))
}
else
return(b(v));
}
-----
(no, I haven't written any unit tests or indeed run it, so it might
not be correct - but you get the idea)

I don't care much about the size of the JS file or about the execution
time (though it must be O(n), of course). To unscramble such code you
would in general need an execution optimizer, which is far from
trivial. Or you could spend a LOT of time on that 30k (original size)
js file to decode it. :)

Are there any tools out there that are capable of doing this? Writing
such code by hand is... well, difficult. ;) But writing such tools
should be doable. Anyone found something like this yet?

Please: refrain from "don't do it" posts. I just want to know what can
be done.

Thanks!

Doug Miller

unread,
Dec 22, 2009, 8:38:55 AM12/22/09
to
In article <21855fc0-131e-4af2...@o28g2000yqh.googlegroups.com>, Andrew <anze...@volja.net> wrote:
>Hi!
>
>I hope I can get close to Sun and avoid the flames... ;)
>
>First of all, I have read and fully understand numerous postings on
>obfuscation.
[snip]

>
>Please: refrain from "don't do it" posts. I just want to know what can
>be done.

While you may have *read* "numerous postings on obfuscation" it is clear that
you do not *understand* them. The *only* way to effectively conceal the
workings of your scripts from prying eyes is to put them on your server.
*Anything* that's delivered client-side can be read by anyone. Since it must
be de-obfuscated by the client, it can be de-obfuscated by anyone with access
to the client (i.e. anyone who clicks on View | Source and takes the time to
read the code).

Lasse Reichstein Nielsen

unread,
Dec 22, 2009, 8:49:40 AM12/22/09
to
spam...@milmac.com (Doug Miller) writes:

I take it you didn't read the message you are replying to.
The idea was to complexify the algorithm by introducing extra operations that
cancel out in the end. The code is never de-obfuscated. It is executed directly
in the obfuscated state.
The code will obviously be less efficient (it does more work to get the
same result), but it's also harder to read an reason about. Not impossible,
only harder.

I don't think anything like that has been made already.

Whether to use it would depend on a complex evaluation taking into
account the extra development complexity of doing the obfuscation, the
extra runtime of the obfuscated code, the importance of hiding the
original code (what would it cost us if someone else had the code) and
the expected threat of someone actually trying to get to the original
code. (I personally think any informed evaluation of that kind would
end in rejecting the idea).

/L 'Still don't think there's code that's worth protecting like that'
--
Lasse Reichstein Holst Nielsen
'Javascript frameworks is a disruptive technology'

Jorge

unread,
Dec 22, 2009, 9:38:04 AM12/22/09
to
On Dec 22, 12:04 pm, Andrew <anzen...@volja.net> wrote:
> (...)

> BUT: I am looking for something that would NOT (only) do the basic
> comments stripping / names renaming, but also changed the (apparent,
> of course) flow of the program. Sth. that would convert:
> -----
> sqrt=function(x) {
>   return(x*x);}
>
> -----
> to sth. like this:
> -----
> b=function(v) {
>   return(a(-v));}
>
> a=function(x) {
>   if (x<4)
>   {
>     a=x+3;
>     b=x-7;
>     c=(x%a)+4;
>     return((b-c)*(b-c))
>   }
>   else
>     return(b(v));}
>
> -----
> (no, I haven't written any unit tests or indeed run it, so it might
> not be correct - but you get the idea)

Awesome idea (!). scrambler(code) ought to be !== scrambler(code) :
the output ought to be as random as possible.
--
Jorge.

Doug Miller

unread,
Dec 22, 2009, 10:00:04 AM12/22/09
to
In article <bphrnm...@gmail.com>, Lasse Reichstein Nielsen <lrn.u...@gmail.com> wrote:
>spam...@milmac.com (Doug Miller) writes:
>
>> In article
> <21855fc0-131e-4af2...@o28g2000yqh.googlegroups.com>, Andrew
> <anze...@volja.net> wrote:
>>>Hi!
>>>
>>>I hope I can get close to Sun and avoid the flames... ;)
>>>
>>>First of all, I have read and fully understand numerous postings on
>>>obfuscation.
>> [snip]
>>>
>>>Please: refrain from "don't do it" posts. I just want to know what can
>>>be done.
>>
>> While you may have *read* "numerous postings on obfuscation" it is clear that
>
>> you do not *understand* them. The *only* way to effectively conceal the
>> workings of your scripts from prying eyes is to put them on your server.
>> *Anything* that's delivered client-side can be read by anyone. Since it must
>> be de-obfuscated by the client, it can be de-obfuscated by anyone with access
>
>> to the client (i.e. anyone who clicks on View | Source and takes the time to
>> read the code).
>
>I take it you didn't read the message you are replying to.

Incorrect.


>The idea was to complexify the algorithm by introducing extra operations that
>cancel out in the end. The code is never de-obfuscated. It is executed directly
>in the obfuscated state.

Yes, I understand that. What both you and the OP overlook is that the issue is
still the same: the entire source code is still clearly visible, and its
operation is obvious to anyone who wishes to take the time to explore it.

>The code will obviously be less efficient (it does more work to get the
>same result), but it's also harder to read an reason about. Not impossible,
>only harder.

Exactly so. And thus useless.

Scott Sauyet

unread,
Dec 22, 2009, 12:24:14 PM12/22/09
to
On Dec 22, 6:04 am, Andrew <anzen...@volja.net> wrote:
> BUT: I am looking for something that would NOT (only) do the basic
> comments stripping / names renaming, but also changed the (apparent,
> of course) flow of the program. Sth. that would convert:
> -----
> sqrt=function(x) {
>   return(x*x);}
>
> -----
> to sth. like this:
> -----
> b=function(v) {
>   return(a(-v));}
>
> a=function(x) {
>   if (x<4)
>   {
>     a=x+3;
>     b=x-7;
>     c=(x%a)+4;
>     return((b-c)*(b-c))
>   }
>   else
>     return(b(v));}
>
> -----
> (no, I haven't written any unit tests or indeed run it, so it might
> not be correct - but you get the idea)

Others can try to tell you how wrong-headed the idea seems (and I
agree with them.) What I want to point out is just how difficult the
process would be. First of all, your source transformations would
presumably need to be one-way, or someone could simply reverse them to
get your code; even if the exact sequence of transformations applied
was randomized, I'm guessing it would be relatively easy to
iteratively test some reversals to see if they simplify the code,
repeating until the code seems simple enough.

And then testing that you haven't broken anything would likely be a
nightmare. The transformed code would almost certainly have its own
artifacts that need to be checked for edge cases.

But you can't even supply a simple working example here. When I try b
(10) in the above, I get 324. Imagine what would go into making
something that's general enough to be useful and could be tested well
enough that it's unlikely to break the scripts it transforms.

-- Scott

Thomas 'PointedEars' Lahn

unread,
Dec 22, 2009, 2:03:53 PM12/22/09
to
Andrew wrote:

> BUT: I am looking for something that would NOT (only) do the basic
> comments stripping / names renaming, but also changed the (apparent,
> of course) flow of the program. Sth. that would convert:
> -----
> sqrt=function(x) {
> return(x*x);
> }
> -----
> to sth. like this:
> -----
> b=function(v) {
> return(a(-v));
> }
> a=function(x) {
> if (x<4)
> {
> a=x+3;
> b=x-7;
> c=(x%a)+4;
> return((b-c)*(b-c))
> }
> else
> return(b(v));
> }
> -----

IIUC, Rice's theorem precludes that from being accomplished.


PointedEars
--
Danny Goodman's books are out of date and teach practices that are
positively harmful for cross-browser scripting.
-- Richard Cornford, cljs, <cife6q$253$1$8300...@news.demon.co.uk> (2004)

Andrew

unread,
Dec 22, 2009, 3:26:13 PM12/22/09
to
Wow, guys... Though I sense the underlying criticism (he, he... ;) I
must say... I'm impressed.

@Doug: thank you for your opinion. :)

@Lasse: that is exactly what I had in mind, nicely put!

I agree, of course one needs to assess if the extra cost is worth it
(of course, there is the "fun" factor in this equation too ;), but
first I wanted to know if there is a tool to do that automatically. It
seems to me it shouldn't be _too_ difficult to write one.

@Jorge: The idea is not mine - it comes from a contest where you had
to manually (as in paper & pencil) decipher what some program does and
simplify it as much as possible.

@Scott:
Yes, that would be another challenge - how to write a program that
deciphers such mangled code. :)
I would say that this is what code optimizers are doing, actually -
trying to optimize our "mangled" code.

As stated, I wrote that example out of my head in less than 2 minutes
- and it shows. Working example would be this:
-----
function b(v) {
return(a(-v));
}

function a(x) {
if (x>7)
{
var a=x+3;
var d=x-7;
c=(a%x)+4;
return((d+c)*(d+c))
}
else
return((x>0)?(x*x):(b(x)));
}

// unit test:
for (x=-100; x<100;x+=0.3)
{
if ( Math.abs(a(x)-x*x) > 0.000001 )
{
alert('Oops! '+a(x)+'!='+(x*x));
break;
}
}
if (x>=100)
alert('Test passed.');
-----
(and it still took me less than 10 minutes while making something
correct and very difficult to read).

But that is beside the point. Such process should of course be
automated and very well tested if it is to be successful.


@PointedEars:


> IIUC, Rice's theorem precludes that from being accomplished.

Could you please elaborate on that? What exactly does it preclude and
why? Surely you don't mean that the code can't be made less readable?

Thank you all for sharing!

Thomas 'PointedEars' Lahn

unread,
Dec 22, 2009, 4:42:27 PM12/22/09
to
Andrew wrote:

> @PointedEars [et al.]:

Please don't, this is not a chat or bulletin board on the Web; it is a
thread-based discussion medium, a newsgroup, instead. Keep attribution
lines that are generated when you post a followup to each separate posting,
in which you should only refer to that posting and optionally its precursors
(as quoted).

<http://jibbering.com/faq/#posting>

>> IIUC, Rice's theorem precludes that from being accomplished.
>
> Could you please elaborate on that? What exactly does it preclude and
> why? Surely you don't mean that the code can't be made less readable?

STFW. According to Wikipedia:

,-<http://en.wikipedia.org/wiki/Rice%27s_theorem>
|
| In computability theory, *Rice's theorem* states that, for any non-trivial
| property of partial functions, there is no general and effective method to
| decide whether an algorithm computes a partial function with that
| property. Here, a property of partial functions is called trivial if it
| holds for all partial computable functions or for none, and an effective
| decision method is called general if it decides correctly for every
| algorithm. The theorem is named after Henry Gordon Rice, and is also known
| as the Rice-Myhill-Shapiro theorem after Rice, John Myhill, and Norman
| Shapiro.

AIUI, that means in a nutshell that you cannot devise a general function
that computes another function that computes the same result for the same
input (a trivial property) as a third function.

Of course an intelligent being, using the approach of informed reasoning
(trial and error), would be able to do that to a certain extent, but an
algorithm-driven machine usually cannot. This is directly connected to the
equally undecidable halting problem which states that a machine cannot
decide if another machine (or itself) holds on a given input (that would be
a trivial property, too).

That does not apply to obfuscation as a whole (so code *can* be made less
readable, if that would be desirable to begin with), but ISTM it does apply
to your approach at obfuscation. And on closer inspection of the Wikipedia
article which uses the very same example in the proof, I think I just did
your homework in theoretical computer science.


PointedEars
--
Prototype.js was written by people who don't know javascript for people
who don't know javascript. People who don't know javascript are not
the best source of advice on designing systems that use javascript.
-- Richard Cornford, cljs, <f806at$ail$1$8300...@news.demon.co.uk>

Andrew

unread,
Dec 22, 2009, 6:53:37 PM12/22/09
to
> > @PointedEars [et al.]:
> Please don't, this is not a chat or bulletin board on the Web; it is a
> thread-based discussion medium, a newsgroup, instead.  Keep attribution

Will do my best, thanks for pointing it out to me.

> >> IIUC, Rice's theorem precludes that from being accomplished.
>
> > Could you please elaborate on that? What exactly does it preclude and
> > why? Surely you don't mean that the code can't be made less readable?
>
> STFW.  According to Wikipedia:

DUSMA. (== Don't Use So Many Acronyms)

> ,-<http://en.wikipedia.org/wiki/Rice%27s_theorem>
> |
> | In computability theory, *Rice's theorem* states that, for any non-trivial
> | property of partial functions, there is no general and effective method to
> | decide whether an algorithm computes a partial function with that
> | property. Here, a property of partial functions is called trivial if it
> | holds for all partial computable functions or for none, and an effective
> | decision method is called general if it decides correctly for every
> | algorithm. The theorem is named after Henry Gordon Rice, and is also known
> | as the Rice-Myhill-Shapiro theorem after Rice, John Myhill, and Norman
> | Shapiro.
>
> AIUI, that means in a nutshell that you cannot devise a general function
> that computes another function that computes the same result for the same
> input (a trivial property) as a third function.

Ah, but my function is not a black box. The program has full control
over inner workings of the function, so this theorem (AIUI == as I
understand it) does not apply to this case.

I have read that exact Wikipedia article - I was asking for further
clarification because nothing in the theorem applies to this case
(IMHO of course).

> Of course an intelligent being, using the approach of informed reasoning
> (trial and error), would be able to do that to a certain extent, but an
> algorithm-driven machine usually cannot.  This is directly connected to the
> equally undecidable halting problem which states that a machine cannot
> decide if another machine (or itself) holds on a given input (that would be
> a trivial property, too).

I was thinking more of a way to replace known constructs with mangled
versions (randomly chosen from a set of predefined options), not of a
way for an algorithm to produce other algorithms automatically. That
would be difficult / impossible?, I agree.

> That does not apply to obfuscation as a whole (so code *can* be made less
> readable, if that would be desirable to begin with), but ISTM it does apply
> to your approach at obfuscation.  And on closer inspection of the Wikipedia
> article which uses the very same example in the proof, I think I just did
> your homework in theoretical computer science.

Well, not really. ISTM (== it seems to me) that the proof only proves
that it is not possible to make a program that would say without doubt
that the mangled function really does what we think it does.
While that would be interesting for testing purposes, it is not
essential for the mangling process I have described.

Anyway, it looks like there is no such tool, and as I am not willing
to invest the time to develop it - so we'll just have to minimize the
JS sources and forget about it. ;)

Again, thank you all for answers, appreciate it.

Peter Michaux

unread,
Dec 22, 2009, 7:06:50 PM12/22/09
to
On Dec 22, 3:53 pm, Andrew <anz...@gmail.com> wrote:

> PointedEars wrote:
> >
> > STFW.  According to Wikipedia:
>
> DUSMA. (== Don't Use So Many Acronyms)

I've asked him many times to type out his acronyms in full as a
courtesy to readers. Like pressing tab in his editor after an acronym
to expand in full would kill him. Probably takes less time than the
time for him to look up the appropriately uncommon, terse acronym just
to confuse readers in the first place. But I guess that is the
"point".

Merry Christmas, Ears.

Peter

Thomas 'PointedEars' Lahn

unread,
Dec 22, 2009, 7:34:50 PM12/22/09
to
Andrew wrote:

> [Thomas 'PointedEars' Lahn wrote:]


>> > @PointedEars [et al.]:
>> Please don't, this is not a chat or bulletin board on the Web; it is a
>> thread-based discussion medium, a newsgroup, instead. Keep attribution
>
> Will do my best, thanks for pointing it out to me.

Yet you removed the attribution line again. (I *know* that you removed it
because Google Groups includes it by default.)

>> >> IIUC, Rice's theorem precludes that from being accomplished.
>> > Could you please elaborate on that? What exactly does it preclude and
>> > why? Surely you don't mean that the code can't be made less readable?
>> STFW. According to Wikipedia:
>
> DUSMA. (== Don't Use So Many Acronyms)

RTFM, HTH.

>> ,-<http://en.wikipedia.org/wiki/Rice%27s_theorem>
>> |
>> | [...]


>>
>> AIUI, that means in a nutshell that you cannot devise a general function
>> that computes another function that computes the same result for the same
>> input (a trivial property) as a third function.
>
> Ah, but my function is not a black box.

That is exactly the point.

> The program has full control over inner workings of the function,

No, it has not.

> so this theorem (AIUI == as I understand it) does not apply to this case.

It does.

>> Of course an intelligent being, using the approach of informed reasoning
>> (trial and error), would be able to do that to a certain extent, but an
>> algorithm-driven machine usually cannot. This is directly connected to
>> the equally undecidable halting problem which states that a machine
>> cannot decide if another machine (or itself) holds on a given input (that
>> would be a trivial property, too).
>
> I was thinking more of a way to replace known constructs with mangled
> versions (randomly chosen from a set of predefined options), not of a
> way for an algorithm to produce other algorithms automatically.

That is the same. In order to choose one randomly (i.e., programmatically)
from a set of predefined options, either the result is so trivial that it is
easily decoded, such as

function f(x)
{
return g(x);
}

function g(x)
{
return Math.pow(x, h(1));
}

function h(x)
{
return 2 * x;
}

or you would need to *decide* programmatically (i.e., using an algorithm)
whether the "predefined option" applies to the algorithm that should be
obfuscated. According to Rice's theorem, that cannot be done.

In addition, any new call that would increase complexity, thus make it
harder to decipher the whole, would decrease efficiency considerably: memory
efficiency because each new function requires a new Function object and a
stack, and runtime efficiency because creating this object and setting up
the stack takes time.

>> That does not apply to obfuscation as a whole (so code *can* be made less
>> readable, if that would be desirable to begin with), but ISTM it does
>> apply to your approach at obfuscation. And on closer inspection of the
>> Wikipedia article which uses the very same example in the proof, I think
>> I just did your homework in theoretical computer science.
>
> Well, not really. ISTM (== it seems to me) that the proof only proves
> that it is not possible to make a program that would say without doubt
> that the mangled function really does what we think it does.

No. What matters is that it is not possible to make a program that would
say without doubt that the mangled function returns the same than the
original function for any given input (here: argument). IOW, it cannot be
computed.


PointedEars
--
var bugRiddenCrashPronePieceOfJunk = (
navigator.userAgent.indexOf('MSIE 5') != -1
&& navigator.userAgent.indexOf('Mac') != -1
) // Plone, register_function.js:16

Lasse Reichstein Nielsen

unread,
Dec 22, 2009, 9:01:27 PM12/22/09
to
Thomas 'PointedEars' Lahn <Point...@web.de> writes:

> AIUI, that means in a nutshell that you cannot devise a general function
> that computes another function that computes the same result for the same
> input (a trivial property) as a third function.

I don't think you can conclude that from Rice's theorem.

It may not be possible to detect, in general, any non-trivial property
of a given partial function, but that doesn't preclude creating a
different (syntax for) a function that behaves the same. You just can't
tell a-priori what the behavior is for all inputs.

Trivial example is eta expansion:
f |-> function(x) { return f(x); }

You can argue whether the latter is a *different* function from "f",
but in this case it's not important. The desired result is a function
that is extensionally equivalent to the original, but with a more
convoluted syntax.

/L

Thomas 'PointedEars' Lahn

unread,
Dec 22, 2009, 9:47:20 PM12/22/09
to
Lasse Reichstein Nielsen wrote:

> Thomas 'PointedEars' Lahn <Point...@web.de> writes:
>> AIUI, that means in a nutshell that you cannot devise a general function
>> that computes another function that computes the same result for the same
>> input (a trivial property) as a third function.
>
> I don't think you can conclude that from Rice's theorem.
>
> It may not be possible to detect, in general, any non-trivial property
> of a given partial function, but that doesn't preclude creating a
> different (syntax for) a function that behaves the same.

Not for an intelligent being, that is. But that was not what was asked.

> You just can't tell a-priori what the behavior is for all inputs.

That is exactly the point of Rice's theorem, and the reason why what the OP
wants cannot be done.

> Trivial example is eta expansion:
> f |-> function(x) { return f(x); }
>
> You can argue whether the latter is a *different* function from "f",
> but in this case it's not important. The desired result is a function
> that is extensionally equivalent to the original, but with a more
> convoluted syntax.

Your example function, when called, would recurse (call itself) until the
stack memory runs out. (So yes, it holds, but not on a Turing machine ;-))

I fail to see how this could disprove anything.

Andrew

unread,
Dec 23, 2009, 5:27:45 AM12/23/09
to
Thomas 'PointedEars' Lahn <PointedE...@web.de> wrote:
> Lasse Reichstein Nielsen wrote:
> > Thomas 'PointedEars' Lahn <PointedE...@web.de> writes:
> >> AIUI, that means in a nutshell that you cannot devise a general function
> >> that computes another function that computes the same result for the same
> >> input (a trivial property) as a third function.
>
> > I don't think you can conclude that from Rice's theorem.
>
> > It may not be possible to detect, in general, any non-trivial property
> > of a given partial function, but that doesn't preclude creating a
> > different (syntax for) a function that behaves the same.
>
> Not for an intelligent being, that is.  But that was not what was asked.

Actually, this might be the point - the set of possible
transformations _would_ be done by an intelligent being (the developer
preparing the mangling system). Only the choice and application of the
transformations would be done by an algorithm (the mangler program).

> > You just can't tell a-priori what the behavior is for all inputs.
>
> That is exactly the point of Rice's theorem, and the reason why what the OP
> wants cannot be done.
>
> > Trivial example is eta expansion:
> >   f  |->  function(x) { return f(x); }
>
> > You can argue whether the latter is a *different* function from "f",
> > but in this case it's not important. The desired result is a function
> > that is extensionally equivalent to the original, but with a more
> > convoluted syntax.
>
> Your example function, when called, would recurse (call itself) until the
> stack memory runs out.  (So yes, it holds, but not on a Turing machine ;-))

I think you misunderstood the syntax - "|->" is not the same as "=".

Enjoy!

Scott Sauyet

unread,
Dec 23, 2009, 1:45:44 PM12/23/09
to
On Dec 22, 3:26 pm, Andrew <anz...@gmail.com> wrote:
> function b(v) {
> return(a(-v));
> }
>
> function a(x) {
> if (x>7)
> {
> var a=x+3;
> var d=x-7;
> c=(a%x)+4;
> return((d+c)*(d+c))
> }
> else
> return((x>0)?(x*x):(b(x)));
> }

But how would you tell your super-obfuscator about the boundary
conditions?

// a(36028797018963969) = 1.2980742146337066e+33
// 36028797018963969 * 36028797018963969 = 1.298074214633707e+33
// a difference of 288230376151711740

So for the value x = 36028797018963969, not only is

a(x) != x * x,

and

Math.abs(a(x) - x * x) > 0, (much greater!)

In other words, even for your simple, hand-tuned function, there are
values for which it does not match the intended function. Perhaps
this input value is irrelevant to your code, but do you have to
indicate to the tool the possible values for every function?

I think you're underestimating the difficulty of creating such a
tool. Moreover, even if you could build it, it would only stop casual
viewers from understanding your code. Anyone who understands
Javascript could, with some perseverance, be able to weed through this
nonsense to understand the core of your programs.

In other words, while I think this is an interesting abstract
discussion, I don't think there are any real chances of building a
tool that does what you want.

-- Scott

Thomas 'PointedEars' Lahn

unread,
Dec 23, 2009, 6:23:56 PM12/23/09
to
Andrew wrote:

> Thomas 'PointedEars' Lahn <PointedE...@web.de> wrote:
>> Lasse Reichstein Nielsen wrote:
>> > Thomas 'PointedEars' Lahn <PointedE...@web.de> writes:
>> >> AIUI, that means in a nutshell that you cannot devise a general
>> >> function that computes another function that computes the same result
>> >> for the same input (a trivial property) as a third function.
>> > I don't think you can conclude that from Rice's theorem.
>> >
>> > It may not be possible to detect, in general, any non-trivial property
>> > of a given partial function, but that doesn't preclude creating a
>> > different (syntax for) a function that behaves the same.
>>
>> Not for an intelligent being, that is. But that was not what was asked.
>
> Actually, this might be the point - the set of possible
> transformations _would_ be done by an intelligent being (the developer
> preparing the mangling system). Only the choice and application of the
> transformations would be done by an algorithm (the mangler program).

You are still missing the point.

>> > Trivial example is eta expansion:
>> > f |-> function(x) { return f(x); }
>>
>> > You can argue whether the latter is a *different* function from "f",
>> > but in this case it's not important. The desired result is a function
>> > that is extensionally equivalent to the original, but with a more
>> > convoluted syntax.
>>
>> Your example function, when called, would recurse (call itself) until the
>> stack memory runs out. (So yes, it holds, but not on a Turing machine
>> ;-))
>
> I think you misunderstood the syntax - "|->" is not the same as "=".

That is true, but it does not matter.

Thomas 'PointedEars' Lahn

unread,
Dec 23, 2009, 6:32:22 PM12/23/09
to
Scott Sauyet wrote:

> In other words, while I think this is an interesting abstract
> discussion, I don't think there are any real chances of building a
> tool that does what you want.

And even if there were, it would not be desirable to use in production code,
for with greater complexity comes less efficiency.

Lasse Reichstein Nielsen

unread,
Dec 23, 2009, 9:22:38 PM12/23/09
to
Thomas 'PointedEars' Lahn <Point...@web.de> writes:

> Lasse Reichstein Nielsen wrote:
>
>> Thomas 'PointedEars' Lahn <Point...@web.de> writes:
>>> AIUI, that means in a nutshell that you cannot devise a general function
>>> that computes another function that computes the same result for the same
>>> input (a trivial property) as a third function.
>>
>> I don't think you can conclude that from Rice's theorem.
>>
>> It may not be possible to detect, in general, any non-trivial property
>> of a given partial function, but that doesn't preclude creating a
>> different (syntax for) a function that behaves the same.
>
> Not for an intelligent being, that is. But that was not what was asked.

Nor for a computer.

>> You just can't tell a-priori what the behavior is for all inputs.
>
> That is exactly the point of Rice's theorem, and the reason why what the OP
> wants cannot be done.

No, Rice's theorem states that there is no total computable function on
the set of algorithms that determines any non-trivial property of the
partial function computed by the algorithm.

Here "algorithms" are programs and the partial functions computed by
algorithm is the runtime behavior of the programs. The theorem simply
says that no non-trivial static analysis can be correct on all
programs (i.e., there is no way to find the runtime behavior of any
program - except to run in at risk non-termination).

The theorem says nothing about rewriting of programs at the syntax
level. It is quite possible to, programmatically, rewrite a program
into another program with the same behavior *without knowing the
behavior*. After all, that's what compilers do all the time: rewrite a
program into another program with the same runtime behavior.

>> Trivial example is eta expansion:
>> f |-> function(x) { return f(x); }
>>
>> You can argue whether the latter is a *different* function from "f",
>> but in this case it's not important. The desired result is a function
>> that is extensionally equivalent to the original, but with a more
>> convoluted syntax.
>
> Your example function, when called, would recurse (call itself) until the
> stack memory runs out. (So yes, it holds, but not on a Turing machine ;-))

Ah, my bad. My ASCII art wasn't self-explanatory :)
The "|->" arrow should represent the "maps-to" symbol (LaTeX \mapsto,
seems to be Unicode code point 0x21a6).

The was to rewrite a function expression into the eta-expanded form.
The expression is extensionally equivalent to the original, and the
program has the same runtime behavior as the original.
(In Javascript, with variadic functions, eta-expansion gets a little
more convoluted).

> I fail to see how this could disprove anything.

It's a rewrite of a Javascript expression that preserves its behavior.
As I read what you have written, Rice's theorem says that this should
not be possible. I claim that it says no such thing.

Andrew

unread,
Dec 27, 2009, 2:00:22 PM12/27/09
to
On Dec 23, 7:45 pm, Scott Sauyet <scott.sau...@gmail.com> wrote:
> In other words, even for your simple, hand-tuned function, there are
> values for which it does not match the intended function.  Perhaps
> this input value is irrelevant to your code, but do you have to
> indicate to the tool the possible values for every function?
>
> I think you're underestimating the difficulty of creating such a
> tool. Moreover, even if you could build it, it would only stop casual
> viewers from understanding your code. Anyone who understands
> Javascript could, with some perseverance, be able to weed through this
> nonsense to understand the core of your programs.

I am beginning to think that the example was not such a good idea...
yes it's flawed. It is an EXAMPLE, not proof of concept. You can do
better if you wish. :)

So, to recap:
- of course it is possible to do it, at least to some extent (still
not buying the Rice's theorem having to do anything with this - as
Lasse pointed out, compilers do that all the time)
- of course this is not the protection against determined hacker (much
better than name replacement though)
- of course there will be performance penalty

> In other words, while I think this is an interesting abstract
> discussion, I don't think there are any real chances of building a
> tool that does what you want.

Well, that might be true. But not because of all the things others
have written in these posts, but because JS is such a difficult
language for this task. I am no way an expert in JS, but from what I
have seen (closures come to mind) there are some concepts that make it
really hard to do this kind of thing. Not impossible, but difficult.

Not sure it would be a bad business idea though - seeing how
obfuscators sell for $60-$250 when they are not even remotely
successful. If someone is capable of doing it, of course. I would have
bought a copy right now, but of course, it would have to be so good
that a capable programmer would have difficulties deducting what the
code does.

Scott Sauyet

unread,
Dec 28, 2009, 10:48:32 AM12/28/09
to
On Dec 27, 2:00 pm, Andrew <anz...@gmail.com> wrote:
> On Dec 23, 7:45 pm, Scott Sauyet <scott.sau...@gmail.com> wrote:
>> [ ... ]

> I am beginning to think that the example was not such a good idea...
> yes it's flawed. It is an EXAMPLE, not proof of concept. You can do
> better if you wish. :)

But the point is that this was an attempt at a simple example. If we
can't get a simple case to work, how likely is it that the more
complicated ones will be workable? Let's take it simpler still. How
about if our mangler had a rule to turn this:

function f(x) {
return x + 1;
}

into this:

function f_prime(x) {
var y = x;
return y + 1;
}

Except noting possible boundary issues, it's pretty clear that we've
maintained the correspondence between f and f_prime. But now what if
we tried it on this:


function g(x) {
eval("var y = y ? y + x : x")
return x + 1
}

to get this:

function g_prime(x) {
var y = x;
eval("var y = y ? y + x : x")
return y + 1
}

Then g(20) = 21, but g_prime(20) = 41.

And of course we could rig it so that the "y" is not easily visible
inside the eval statement. The point is that this really is
difficult.


> - of course it is possible to do it, at least to some extent (still
> not buying the Rice's theorem having to do anything with this - as
> Lasse pointed out, compilers do that all the time)

I'm certainly not buying Thomas Lahn's assertion that Rice's theorm
implies that

| [Y]ou cannot devise a general function that computes another


function
| that computes the same result for the same input (a trivial
property)
| as a third function.

I think the Y-Combinator [1] demonstrates that this is false.

But I also think Lasse Nielsen is overstating when he says that this
is so similar to what a compiler does. A compiler is doing something
akin to transcription. I think your mangler would have to do
something closer to translation. While I have read Hofstadter [2] and
understand something about how difficult it might be to draw the line
between the two, I think it makes a difference in how easy it would be
to create an algorithm for one versus the other.


>> In other words, while I think this is an interesting abstract
>> discussion, I don't think there are any real chances of building a
>> tool that does what you want.
>
> Well, that might be true. But not because of all the things others
> have written in these posts, but because JS is such a difficult
> language for this task. I am no way an expert in JS, but from what I
> have seen (closures come to mind) there are some concepts that make it
> really hard to do this kind of thing. Not impossible, but difficult.

Actually, I think closures would be one of the best tools to use to
accomplish some obfuscation.

function f_prime2 = (function(test) {
var y = test ? 0 : 1;
return function(x) {
return x + y;
}
})(false);

This is already fairly obfuscated from the original function, and I
can clearly imagine additional layers. But I don't see that as likely
to hide much from even a mildly persistent snoop.

I think the worst problem would come with "eval" and its cousins.


> Not sure it would be a bad business idea though - seeing how
> obfuscators sell for $60-$250 when they are not even remotely
> successful. If someone is capable of doing it, of course. I would have
> bought a copy right now, but of course, it would have to be so good
> that a capable programmer would have difficulties deducting what the
> code does.


I think the best assessment in this thread was in Lasse Nielsen's
first response where he discussed the factors to be considered in
approaching this type of tool and concluding:

| I personally think any informed evaluation of that kind would

| end in rejecting the idea.

It's not that something couldn't be built. Clearly someone could
build a tool that would accomplish much of what you suggest. But as
the inputs got more complicated, it's more and more likely that the
tool would actually break working code, and of course it would be by
design much more difficult to debug the issues that arose.

-- Scott

[1] http://en.wikipedia.org/wiki/Fixed_point_combinator
[2] http://en.wikipedia.org/wiki/Metamagical_Themas

Message has been deleted

Thomas 'PointedEars' Lahn

unread,
Dec 28, 2009, 6:49:04 PM12/28/09
to
[Cancel & Supersedes]

Scott Sauyet wrote:

> Andrew wrote:
>> - of course it is possible to do it, at least to some extent (still
>> not buying the Rice's theorem having to do anything with this - as
>> Lasse pointed out, compilers do that all the time)
>
> I'm certainly not buying Thomas Lahn's assertion that Rice's theorm
> implies that
>
> | [Y]ou cannot devise a general function that computes another
> | function that computes the same result for the same input
> | (a trivial property) as a third function.
>
> I think the Y-Combinator [1] demonstrates that this is false.

I do not think the Y-Combinator applies here. Especially, we can read
where "Y-combinator" redirects to:

,-<http://en.wikipedia.org/wiki/Fixed_point_combinator>
|
| A fixed point combinator (or fixed-point operator) is a higher-order
| function that computes a fixed point of other functions. A fixed point
| of a function f is a value x such that f(x) = x. For example, 0 and 1
| are fixed points of the function f(x) = x2, because 02 = 0 and 12 = 1.
| Whereas a fixed-point of a first-order function (a function on "simple"
| values such as integers) is a first-order value, a fixed point of a
| higher-order function f is another function p such that f(p) = p.
| A fixed point combinator, then, is a function g which produces such a
| fixed point p for any function f:
|
| p = g(f), f(p) = p
|
| or, alternately:
|
| f(g(f)) = g(f).
|
| Because fixed-point combinators are higher-order functions, their history
| is intimately related to the development of lambda calculus. One well
| known fixed point combinator in the untyped lambda calculus is Haskell
| Curry's Y = ?f�(?x�f (x x)) (?x�f (x x)). The name of this combinator is
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| incorrectly used sometimes to refer to any fixed point combinator. The
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| untyped lambda calculus however, contains an infinity of fixed point
| combinators. Fixed point combinators do not necessarily exist in more
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| restrictive models of computation. For instance, they do not exist in
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| simply typed lambda calculus.

As for Rice's theorem:

<http://en.wikipedia.org/wiki/Rice%27s_theorem#Proof_by_reduction_from_the_halting_problem>

| Proof by reduction from the halting problem
| ---------------------------------------------------------------------
|
| Proof sketch
|
| Suppose, for concreteness, that we have an algorithm for examining
| a program p and determining infallibly whether p is an implementation
| of the squaring function, which takes an integer d and returns d^2.
| The proof works just as well if we have an algorithm for deciding any
| other nontrivial property of programs, and will be given in general
| below.
|
| The claim is that we can convert our algorithm for identifying
| squaring programs into one which identifies functions that halt.
| We will describe an algorithm which takes inputs a and i and
| determines whether program a halts when given input i.
|
| The algorithm is simple: we construct a new program t which (1)
| temporarily ignores its input while it tries to execute program a on
| input i, and then, if that halts, (2) returns the square of its input.
| Clearly, t is a function for computing squares if and only if step (1)
| halts. Since we've assumed that we can infallibly identify program for
| computing squares, we can determine whether t is such a program, and
| therefore whether program a halts on input i. Note that we needn't
| ctually execute t; we need only decide whether it is a squaring program,
| and, by hypothesis, we know how to do this.
|
| t(n) {
| a(i)
| return n�n
| }
|
| This method doesn't depend specifically on being able to recognize
| functions that compute squares; as long as some program can do what
| we're trying to recognize, we can add a call to a to obtain our t.
| We could have had a method for recognizing programs for computing
| square roots, or programs for computing the monthly payroll, or
| programs that halt when given the input "Abraxas", or programs that
| commit array bounds errors; in each case, we would be able to solve
| the halting problem similarly.
|
| [Following the proof that this cannot be done, because if it were
| doable that would mean the halting problem was decidable, which
| it is not.]

Now, in order to write a program `P' that obfuscates code in a way that
statements are replaced by more complex code (e.g., function calls) that
computes the same as the original code for any given input, that program
`P' must be able to recognize, for example, a set of statements that is an
implementation of the squaring function as such a program `p'. Since the
proof above shows that this is not possible, there cannot be such a program
`P' (even if there can be such programs `p' or `t', which was not disputed
before).

A corollary of this is what I originally stated: If you cannot
programmatically determine if a set of statements is an implementation of a
certain function `p', you can _not_ write a program `P' that computes or
selects another function `t' that computes the same values as this set of
statements for the same inputs.

I find it rather curious that nobody appears to have recognized that even
though the proof for Rice's theorem in the Wikipedia is based on the very
same trivial property that the OP used in their question (the squaring
function), and I pointed that out in my answer.


PointedEars
--
realism: HTML 4.01 Strict
evangelism: XHTML 1.0 Strict
madness: XHTML 1.1 as application/xhtml+xml
-- Bjoern Hoehrmann

Scott Sauyet

unread,
Dec 29, 2009, 10:50:14 AM12/29/09
to
On Dec 28, 6:49 pm, Thomas 'PointedEars' Lahn <PointedE...@web.de>
wrote:

> Scott Sauyet wrote:
>> Andrew wrote:
>>> - of course it is possible to do it, at least to some extent (still
>>> not buying the Rice's theorem having to do anything with this - as
>>> Lasse pointed out, compilers do that all the time)
>
>> I'm certainly not buying Thomas Lahn's assertion that Rice's theorm
>> implies that
>
>> | [Y]ou cannot devise a general function that computes another
>> | function that computes the same result for the same input
>> | (a trivial property) as a third function.
>
>> I think the Y-Combinator [1] demonstrates that this is false.
>
> I do not think the Y-Combinator applies here.  Especially, we can read
> where "Y-combinator" redirects to:
>
> ,-<http://en.wikipedia.org/wiki/Fixed_point_combinator>

Which, incidentally, is the exact link I supplied.


> | [ ... ] The name of this combinator is


>                                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> | incorrectly used sometimes to refer to any fixed point combinator.

>   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

However, I did not misuse the term. I used the Y-combinator as the
best-known example of a fixed-point combinator. Since it was a
demonstration of existence, one example is plenty.

> | [ ... ] Fixed point combinators do not necessarily exist in more


>                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> | restrictive models of computation. For instance, they do not exist in
>   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> | simply typed lambda calculus.

But it does exist in Javascript. A quick web search turns up numerous
examples. This is my preferred form:

var Y = function(f) {
return (function(g) {
return g(g);
})(function(h) {
return function() {
return f(h(h)).apply(null, arguments);
};
});
};

Can you find a function f and a value x such that the following do not
yield the same result:

f(x)
Y(function() {return f;})(x)

?

> As for Rice's theorem:

> <http://en.wikipedia.org/wiki/Rice%27s_theorem#Proof_by_reduction_from...>


> | Proof by reduction from the halting problem

Yes, we all know how to read Wikipedia...

> Now, in order to write a program `P' that obfuscates code in a way that
> statements are replaced by more complex code (e.g., function calls) that
> computes the same as the original code for any given input, that program
> `P' must be able to recognize, for example, a set of statements that is an
> implementation of the squaring function as such a program `p'.

No, it doesn't have to do that. I could replace every function in the
original program with another that computes the same result, but which
is syntactically more complicated. This does not go very far towards
the OP's goal, though, as I'm sure it would be straightforward to
write code to recognize and reverse this transformation.


> Since the
> proof above shows that this is not possible, there cannot be such a program
> `P' (even if there can be such programs `p' or `t', which was not disputed
> before).

Sorry, I don't understand the parenthetical remark. But your
conclusion is clearly based upon a misreading of Rice's Theorem.


> A corollary of this is what I originally stated: If you cannot
> programmatically determine if a set of statements is an implementation of a
> certain function `p', you can _not_ write a program `P' that computes or
> selects another function `t' that computes the same values as this set of
> statements for the same inputs.

But you don't necessarily have to come at this from that direction.
You don't have to demonstrate an understanding of any set of
statements. You can do these transformations at the syntactic level,
using, for example, a fixed-point combinator like the Y-combinator on
the functions presented.

I'm not trying to support the OP. I think the idea is not well-
conceived, and that even if it were to work reasonably well, it would
cause more problems than it could possibly solve, but Rice's theorem
is not relevant.

You didn't respond to Lasse Nielsen's last post, but, if you're right
that Rice's theorem says that you cannot programatically convert a
function to another of identical behavior, how do explain the
existence of compilers?

> I find it rather curious that nobody appears to have recognized that even
> though the proof for Rice's theorem in the Wikipedia is based on the very
> same trivial property that the OP used in their question (the squaring
> function), and I pointed that out in my answer.

That means only that we can't algorithmically recognize any and all
sets of statements that represent squaring functions. It doesn't
imply that we can't transform one squaring function into another.

Do you think the following functions are equally transparent?:

var f1 = function(s) {return x * x;}

var f2 = (function(f) {
return (function(g) {
return g(g);
})(function(h) {
return function() {
return f(h(h)).apply(null, arguments);
};
});
})(function() {
return function(x) {return x * x;}
});

The second is simply the result of the Y-combinator applied to the
first.

We're pretty far afield from the OP's goals, though. The thread has
given a pretty strong consensus that those goals are at best very
difficult and, even if attainable, are not worth pursuing.

-- Scott

Scott Sauyet

unread,
Dec 29, 2009, 12:08:10 PM12/29/09
to
On Dec 29, 10:50 am, I <scott.sau...@gmail.com> wrote:
> Do you think the following functions are equally transparent?:
>
>     var f1 = function(s) {return x * x;}
^^^
Sorry, typo:

var f1 = function(x) {return x * x;}

-- Scott

Thomas 'PointedEars' Lahn

unread,
Dec 29, 2009, 12:46:44 PM12/29/09
to
Scott Sauyet wrote:

> Thomas 'PointedEars' Lahn wrote:
>> As for Rice's theorem:
>>
<http://en.wikipedia.org/wiki/Rice%27s_theorem#Proof_by_reduction_from...>
>> | Proof by reduction from the halting problem
>
> Yes, we all know how to read Wikipedia...

Apparently not.

> You didn't respond to Lasse Nielsen's last post, but, if you're right
> that Rice's theorem says that you cannot programatically convert a
> function to another of identical behavior, how do explain the
> existence of compilers?

A compiler transforms source code into machine-dependent code; IOW, it
translates one higher-level language into another, lower-level language.
That is a concept fundamentally different from that which Rice's theorem
addresses.

>> I find it rather curious that nobody appears to have recognized that
>> even though the proof for Rice's theorem in the Wikipedia is based on
>> the very same trivial property that the OP used in their question (the
>> squaring function), and I pointed that out in my answer.
>
> That means only that we can't algorithmically recognize any and all
> sets of statements that represent squaring functions.

It means that no *program* can do that.

> It doesn't imply that we can't transform one squaring function into
> another.

It does imply that a *program* cannot do that.

> Do you think the following functions are equally transparent?:
>
> var f1 = function(s) {return x * x;}
>
> var f2 = (function(f) {
> return (function(g) {
> return g(g);
> })(function(h) {
> return function() {
> return f(h(h)).apply(null, arguments);
> };
> });
> })(function() {
> return function(x) {return x * x;}
> });
>
> The second is simply the result of the Y-combinator applied to the
> first.

What you are still missing is that the "Y-combinator" was applied by *you*
here, an (arguably) intelligent being applying informed reasoning; _not_ a
program implementing an algorithm. For a simple implementation of the
example used in the proof for Rice's theorem, a program implementing an
algorithm would need to recognize whether f() in

function a(j)
{
while (--j) b(j);
}

function f(x)
{
a(i);
return x * x;
}

was an implementation of the squaring function or not in order to compute
or select a suitable replacement for obfuscation. It cannot do that
because it depends on the pre-call value of `i' (and the behavior of b(j)),
whether a(i) halts, and if it halts, if execution even reaches the `return'
statement in f(), *regardless* that it is there. And the program cannot
recognize whether a(i), i.e. the while-loop in it, halts, let alone
whether, if it halts, the `return' statement in f() is ever reached.

> We're pretty far afield from the OP's goals, though.

Obfuscation was part of the goal, and that has been attained to a certain
degree. However, it has necessarily _not_ been attained *through a
program*, of course, and so missing the other part, of course.

> The thread has given a pretty strong consensus that those goals are at
> best very difficult and, even if attainable, are not worth pursuing.

ACK

Scott Sauyet

unread,
Dec 29, 2009, 5:49:26 PM12/29/09
to
On Dec 29, 12:46 pm, Thomas 'PointedEars' Lahn <PointedE...@web.de>
wrote:

> Scott Sauyet wrote:
>> Thomas 'PointedEars' Lahn wrote:
>> Yes, we all know how to read Wikipedia...
>
> Apparently not.

True, it's pretty clear that at least one person in this thread
doesn't properly understand the implications of Rice's theorem! :-)


>> You didn't respond to Lasse Nielsen's last post, but, if you're right
>> that Rice's theorem says that you cannot programatically convert a
>> function to another of identical behavior, how do explain the
>> existence of compilers?
>
> A compiler transforms source code into machine-dependent code; IOW, it
> translates one higher-level language into another, lower-level language.  
> That is a concept fundamentally different from that which Rice's theorem
> addresses.

Right, but the form of obfuscation that Lasse and I are suggesting is
closer to that than to a transformation at the algorithmic level. No
one is saying that we have to know that a particular function computes
square roots in order to transform it. The point is that no matter
what a function does, we can transform it in various syntactic manners
that do not change its behavior. I still don't think it's worthwhile
doing, and I think anything that could be done like this is as subject
to reversal as is, say, minification, but you seem to be missing the
point that the only comprehension of the program required for this
particular transformation is to recognize function declarations. We
don't have to in any way understand them.


>>> I find it rather curious that nobody appears to have recognized that
>>> even though the proof for Rice's theorem in the Wikipedia is based on
>>> the very same trivial property that the OP used in their question (the
>>> squaring function), and I pointed that out in my answer.
>
>> That means only that we can't algorithmically recognize any and all
>> sets of statements that represent squaring functions.
>
> It means that no *program* can do that.

No, it's broader than that. It means there is no algorithm that can
do this (assuming there is no brute-force mechanism that can test all
possible inputs.) A program can be thought of a representation of an
algorithm in a particular language; Rice's theorem is stronger in that
it's formal algorithms rejected.


>> It doesn't imply that we can't transform one squaring function into
>> another.
>
> It does imply that a *program* cannot do that.

Note the word "function". I defy you to find a Javascript squaring
*function*, f, for which the Y-combinator applied to a function
returning f will not also yield a squaring function defined on the
same domain.


>> [ description of Y-combinator applied to a particular function ]


>>
> What you are still missing is that the "Y-combinator" was applied by *you*
> here, an (arguably) intelligent being applying informed reasoning; _not_ a
> program implementing an algorithm.  For a simple implementation of the
> example used in the proof for Rice's theorem, a program implementing an
> algorithm would need to recognize whether f() in
>
>   function a(j)
>   {
>     while (--j) b(j);
>   }
>
>   function f(x)
>   {
>     a(i);
>     return x * x;
>   }
>
> was an implementation of the squaring function or not in order to compute
> or select a suitable replacement for obfuscation.

No, I contend that without analyzing the behavior of 'a' or 'f' above,
these definitions will have the same formal behavior, for any given
values of 'b', 'i', and 'x':

var a = (function(f) {


return (function(g) {
return g(g);
})(function(h) {
return function() {
return f(h(h)).apply(null, arguments);
};
});
})(function() {

return function(j) {while (--j) b(j);}
});


var f = (function(f) {


return (function(g) {
return g(g);
})(function(h) {
return function() {
return f(h(h)).apply(null, arguments);
};
});
})(function() {
return function(x) {

a(i);
return x * x;
}

});

I am not about to try to write a Javascript parser to prove that this
can be done syntactically, but the algorithm is simple:

For every function definition in the input with name ~n~, parameter
list ~p~, and body ~b~, replace that definition in the output with

var ~name~ = (function(f) {


return (function(g) {
return g(g);
})(function(h) {
return function() {
return f(h(h)).apply(null, arguments);
};
});
})(function() {

return function(~p~) {
~b~
}
});

I simply *don't care* that one of these functions putatively computes


the square of its input.

>  It cannot do that
> because it depends on the pre-call value of `i' (and the behavior of b(j)),
> whether a(i) halts, and if it halts, if execution even reaches the `return'
> statement in f(), *regardless* that it is there.  And the program cannot
> recognize whether a(i), i.e. the while-loop in it, halts, let alone
> whether, if it halts, the `return' statement in f() is ever reached.

Can you find values of 'i', 'b', and 'x' for which the formal behavior
of my replacement code differs from your original? I know that it
will be less performant, but besides that, can you find differences?


>> We're pretty far afield from the OP's goals, though.
>
> Obfuscation was part of the goal, and that has been attained to a certain
> degree.  However, it has necessarily _not_ been attained *through a
> program*, of course, and so missing the other part, of course.

No one has written a program, it's true. But we've described
algorithms which could be implemented by someone who knows how to
write a Javascript parser/transformer.

You're an (arguably :-) ) intelligent person. Can you tell me what's
wrong with the following argument:

| Removing extraneous white space in a program is something a human
| can do, but this sort of minification cannot be done by a program
| because of restrictions described in the Wikipedia article on
| Rice's Theorem.
|
| Rice's Theorm means in a nutshell that you cannot devise a general


| function that computes another function that computes the same
| result for the same input (a trivial property) as a third
| function.
|

| Of course an intelligent being, using the approach of informed
| reasoning (trial and error), would be able to do that to a certain
| extent, but an algorithm-driven machine usually cannot. This is
| directly connected to the equally undecidable halting problem
| which states that a machine cannot decide if another machine (or
| itself) holds on a given input (that would be a trivial property,
| too).
|

| That does not apply to obfuscation as a whole (so code *can* be
| made less readable, if that would be desirable to begin with), but

| ISTM it does apply to your approach at minification.

Or do you believe that minimizers can't work?

Cheers,

-- Scott

Thomas 'PointedEars' Lahn

unread,
Dec 29, 2009, 6:25:27 PM12/29/09
to
Scott Sauyet wrote:

> Thomas 'PointedEars' Lahn wrote:
>> Scott Sauyet wrote:
>>> Thomas 'PointedEars' Lahn wrote:
>>> Yes, we all know how to read Wikipedia...
>> Apparently not.
>
> True, it's pretty clear that at least one person in this thread
> doesn't properly understand the implications of Rice's theorem! :-)

I am counting at least two.

>>> You didn't respond to Lasse Nielsen's last post, but, if you're right
>>> that Rice's theorem says that you cannot programatically convert a
>>> function to another of identical behavior, how do explain the
>>> existence of compilers?
>>
>> A compiler transforms source code into machine-dependent code; IOW, it
>> translates one higher-level language into another, lower-level language.
>> That is a concept fundamentally different from that which Rice's theorem
>> addresses.
>
> Right, but the form of obfuscation that Lasse and I are suggesting is

> closer to that than to a transformation at the algorithmic level. [...]

IOW, it was a red herring.

>>> It doesn't imply that we can't transform one squaring function into
>>> another.
>> It does imply that a *program* cannot do that.
>
> Note the word "function". I defy you to find a Javascript squaring
> *function*, f, for which the Y-combinator applied to a function
> returning f will not also yield a squaring function defined on the
> same domain.

You are still missing the point. Finding the squaring function
is what the program needs to do (not me), and which it can not.

> [...] I contend that without analyzing the behavior of 'a' or 'f' above,


> these definitions will have the same formal behavior, for any given
> values of 'b', 'i', and 'x':
>
> var a = (function(f) {
> return (function(g) {
> return g(g);
> })(function(h) {
> return function() {
> return f(h(h)).apply(null, arguments);
> };
> });
> })(function() {
> return function(j) {while (--j) b(j);}
> });
>
>
> var f = (function(f) {
> return (function(g) {
> return g(g);
> })(function(h) {
> return function() {
> return f(h(h)).apply(null, arguments);
> };
> });
> })(function() {
> return function(x) {
> a(i);
> return x * x;
> }
> });

Thank you, I rest my case. The "Y-combined" variant will break in various
implementations that do not provide Function.prototype.apply() to begin
with. IOW, it does _not_ have the same formal behavior.

>>> We're pretty far afield from the OP's goals, though.
>>
>> Obfuscation was part of the goal, and that has been attained to a
>> certain degree. However, it has necessarily _not_ been attained
>> *through a program*, of course, and so missing the other part, of
>> course.
>
> No one has written a program, it's true. But we've described
> algorithms which could be implemented by someone who knows how to
> write a Javascript parser/transformer.

No.



> You're an (arguably :-) ) intelligent person. Can you tell me what's

> wrong with the following argument: [...]

Since you now have begun making up arguments in order to make arguments,
we better end this discussion.

PointedEars
--
Use any version of Microsoft Frontpage to create your site.
(This won't prevent people from viewing your source, but no one
will want to steal it.)
-- from <http://www.vortex-webdesign.com/help/hidesource.htm> (404-comp.)

Scott Sauyet

unread,
Dec 29, 2009, 8:52:24 PM12/29/09
to
On Dec 29, 6:25 pm, Thomas 'PointedEars' Lahn <PointedE...@web.de>

wrote:
> Scott Sauyet wrote:
>> Thomas 'PointedEars' Lahn wrote:
>>> Scott Sauyet wrote:
>>>> Thomas 'PointedEars' Lahn wrote:

>>> A compiler transforms source code into machine-dependent code; IOW, it
>>> translates one higher-level language into another, lower-level language.
>>> That is a concept fundamentally different from that which Rice's theorem
>>> addresses.
>
>> Right, but the form of obfuscation that Lasse and I are suggesting is
>> closer to that than to a transformation at the algorithmic level. [...]
>
> IOW, it was a red herring.

No, it was something that could help towards the OP's goals. A
transformation of one program into another with the same behavior but
with syntax harder for the casual reader to understand.


>>>> It doesn't imply that we can't transform one squaring function into
>>>> another.
>>> It does imply that a *program* cannot do that.
>
>> Note the word "function".  I defy you to find a Javascript squaring
>> *function*, f,  for which the Y-combinator applied to a function
>> returning f will not also yield a squaring function defined on the
>> same domain.
>
> You are still missing the point.  Finding the squaring function
> is what the program needs to do (not me), and which it can not.

Did you really not read my last response? This is purely syntactic.

Why should the obfuscator locate the squaring function? It will
transform all functions, or perhaps a random sample of them to make it
more difficult to reverse. It doesn't need to care what the functions
mean.

The prosecution declines to give a closing argument. With the
defense's lack of a reasonable case, there is no need.

Is that really your argument? Really?

So in versions that don't match ES3 15.3.4.3, this technique won't
work? You know what else? It won't work if you translate your code
into Swahili either. So what? And that's not even an essential
portion of the Y-combinator. There are versions around that do not
use Function.prototype.appy. [1] [2]

Still, in the vastly restricted environment of those implementations
that do manage to correctly implement Function.prototype.apply, can
you point to a difference in behavior?


>>> Obfuscation was part of the goal, and that has been attained to a
>>> certain degree.  However, it has necessarily _not_ been attained
>>> *through a program*, of course, and so missing the other part, of
>>> course.
>
>> No one has written a program, it's true.  But we've described
>> algorithms which could be implemented by someone who knows how to
>> write a Javascript parser/transformer.
>
> No.

Ah, what a witty riposte! What intellectual fortitude it took to
devise such a clever reply! What a fantastic debater my opponent has
shown himself to be!

Can you explain what is wrong with the algorithm I applied? Or are
you still going to claim that I'm cheating by relying on
Function.prototype.apply?


>> You're an (arguably :-) ) intelligent person.  Can you tell me what's
>> wrong with the following argument: [...]
>
> Since you now have begun making up arguments in order to make arguments,
> we better end this discussion.

Well, if you wish, of course. But I'm sure everyone reading this
thread recognizes the argument you deleted as a simple variation of
your argument that Rice's theorem implies that you can't create
transformations of source code that retain the formal behavior of the
original code but are reasonably obfuscated. Can you point out how
the arguments differ or confirm that you don't believe minifiers can
work?

-- Scott

[1] http://thraxil.org/users/anders/posts/2008/09/15/My-Own-Javascript-Y-Combinator/
[2] http://matt.might.net/articles/implementation-of-recursive-fixed-point-y-combinator-in-javascript-for-memoization/

Lasse Reichstein Nielsen

unread,
Dec 29, 2009, 10:02:58 PM12/29/09
to
Thomas 'PointedEars' Lahn <Point...@web.de> writes:

> A compiler transforms source code into machine-dependent code;

No, that's a special case of a compiler. In generality, a compiler
transforms a program in one language into an equivalent program in
another language. The other language may be machine-code, or it may
not. It may not even be a different language from the first.
Or you can compile C++ to C, or Java to C, or C to JavaScript.
Or JavaScript to JavaScript.


> IOW, it
> translates one higher-level language into another, lower-level language.
> That is a concept fundamentally different from that which Rice's theorem
> addresses.

Yes. And it's different independently of an (arbitrary or not)
assignment of level to languages.

>> It doesn't imply that we can't transform one squaring function into
>> another.
>
> It does imply that a *program* cannot do that.

No. As long as the program doesn't depend on understanding the meaning
of its input, only its syntax.

Ira Baxter

unread,
Jan 5, 2010, 11:21:50 AM1/5/10
to

"Doug Miller" <spam...@milmac.com> wrote in message
news:hgqmtm$d77$2...@news.eternal-september.org...
> In article <bphrnm...@gmail.com>, Lasse Reichstein Nielsen
> <lrn.u...@gmail.com> wrote:
>>spam...@milmac.com (Doug Miller) writes:
>>
>>> In article
>> <21855fc0-131e-4af2...@o28g2000yqh.googlegroups.com>,
>> Andrew
>> <anze...@volja.net> wrote:


> Yes, I understand that. What both you and the OP overlook is that the
> issue is
> still the same: the entire source code is still clearly visible, and its
> operation is obvious to anyone who wishes to take the time to explore it.

"Obvious"? "take the time"? You can reduce the problem of code understanding
to the Turing Tarpit, which is in effect provably impossible.
You should read the following paper on how to make extremely
difficult obfuscation:

http://math.auckland.ac.nz/bitstream/2292/4398/1/0674154.pdf

(and even real programs written by people without obfuscation can
be extremely hard to understand, espeically if they are buggy).

Now whether it is worth it to do this for all Javascript codes, or even
some of it, is another matter. People place different values on
their work.

>>The code will obviously be less efficient (it does more work to get the
>>same result), but it's also harder to read an reason about. Not
>>impossible,
>>only harder.

Not impossible, but hard enough so you need an arbitrarily large amount
of theorem proving to analyze it. That might not be impossible in
the abstract, but its damn hard to distinguish the two.


--
Ira Baxter, CTO
www.semanticdesigns.com

Andrew

unread,
Jan 6, 2010, 7:46:19 AM1/6/10
to
On Dec 29 2009, 6:46 pm, Thomas 'PointedEars' Lahn

<PointedE...@web.de> wrote:
> Scott Sauyet wrote:
> > You didn't respond to Lasse Nielsen's last post, but, if you're right
> > that Rice's theorem says that you cannot programatically convert a
> > function to another of identical behavior, how do explain the
> > existence of compilers?
>
> A compiler transforms source code into machine-dependent code; IOW, it
> translates one higher-level language into another, lower-level language.  
> That is a concept fundamentally different from that which Rice's theorem
> addresses.

Ok, then, let's use JS minimizers and obfuscators as an example
(instead of compilers). They transform source code so that it is
written in another way, yet it performs the same as it did.
Not that they are useful for this case, but they are instant proof
that such transformations are possible - and by automated tools too.

> > The thread has given a pretty strong consensus that those goals are at
> > best very difficult and, even if attainable, are not worth pursuing.

+1. :)

Thank you all for answering, it's been an interesting discussion.
Happy coding!

Jorge

unread,
Jan 6, 2010, 7:57:00 AM1/6/10
to
On Jan 6, 1:46 pm, Andrew <anz...@gmail.com> wrote:
>
> > > The thread has given a pretty strong consensus that those goals
> > > (...) are not worth pursuing.
>
> +1. :)

-1. :-)
--
Jorge.

Andrew

unread,
Jan 6, 2010, 8:18:03 AM1/6/10
to
On Jan 5, 5:21 pm, "Ira Baxter" <idbax...@semdesigns.com> wrote:
> You should read the following paper on how to make extremely
> difficult obfuscation:
>
> http://math.auckland.ac.nz/bitstream/2292/4398/1/0674154.pdf

The link doesn't work and it seems their webpage has some difficulties
(results on Google all point to another, nonexisting server - I guess
they are doing the redirect poorly), while their own search finds
nothing on 'obfuscation'.

Any chance you could provide a better link or path to the file?

Thanks!

Andrew

unread,
Jan 6, 2010, 8:25:24 AM1/6/10
to
On Jan 6, 2:18 pm, Andrew <anz...@gmail.com> wrote:
> On Jan 5, 5:21 pm, "Ira Baxter" <idbax...@semdesigns.com> wrote:
>
> > You should read the following paper on how to make extremely
> > difficult obfuscation:
>
> >http://math.auckland.ac.nz/bitstream/2292/4398/1/0674154.pdf
>
> Any chance you could provide a better link or path to the file?

Nevermind, I think i found it:
Design and Evaluation of Slicing Obfuscations
Stephen Drape and Anirban Majumdar
http://www.cs.auckland.ac.nz/CDMTCS/researchreports/311stephen.pdf

Looks like an interesting read, thank you! (if you had something else
in mind, please repost the link)

Scott Sauyet

unread,
Jan 6, 2010, 9:16:48 AM1/6/10
to
On Jan 6, 7:57 am, Jorge <jo...@jorgechamorro.com> wrote:
>>>> The thread has given a pretty strong consensus that those goals
>>>> (...) are not worth pursuing.
>
> -1. :-)

I'm curious as to why. Do you see a compelling case for trying to
obfuscate Javascript source, even to the likely detriment of its
performance?

This thread turned into a discussion of possible means and of
theoretical obstacles, but outside your initial brief comment, I've
seen little from you or anyone else to suggest that this really is
worth actually trying. Do you still think it is? If so, why?

-- Scott

Jorge

unread,
Jan 6, 2010, 11:02:30 AM1/6/10
to
Ba Wna 1, 8:61 cz, Fpbgg Fnhlrg <fpbgg.fnh...@tznvy.pbz> jebgr:
>
> ... V'ir
> frra yvggyr sebz lbh be nalbar ryfr gb fhttrfg gung guvf ernyyl vf
> jbegu npghnyyl gelvat.  Qb lbh fgvyy guvax vg vf?

Lrf.

> Vs fb, jul?

Gb znxr yrff boivbhf gur qrgnvyf bs lbhe pbqr.
--
Wbetr.

Jorge

unread,
Jan 6, 2010, 11:05:03 AM1/6/10
to

Scott Sauyet

unread,
Jan 6, 2010, 11:17:52 AM1/6/10
to

I really was hoping for a little more detail!

I understand that we would do obfuscation in order to "make less
obvious the details of your code." That's really a tautology. But
it's not just a matter of rot13ing (!) the text. The OP was talking
about a technique beyond minimizing, variable-renaming, and packing,
one which would make it prohibitively time-consuming to understand the
basics of how the code works. Clearly it would not make it
impossible. Black-box testing might eventually get most of the way
there, and any semantics-preserving transformation would presumably be
in theory reversible enough that a really determined hacker would get
through it all.

I guess the question is do you think there is code that is both worth
this level of protection and unimportant enough to accept what would
quite possibly be a noticeable degradation in performance? Moreover,
are you willing to take the debugging hit as well, since if these
transformations are susceptible error, you would have issues where the
transformed code might not do what the untransformed code does? What
sort of code would you use this for?

-- Scott

Jorge

unread,
Jan 6, 2010, 2:07:52 PM1/6/10
to
On Jan 6, 5:17 pm, Scott Sauyet <scott.sau...@gmail.com> wrote:

(Why ? What for ?)

IzpaMvOzqacwrKVhVSLtrKM9pvOaqKMzVUu7LKRtLaZtM8I7LKEzVQbgXFOT
pzIcpzHtMaMkpvjtIvO6ozylVP6iozMlpFOvLFODMJWjrUAvMKRaMvO8Mac7
LF0jYFOjLacwqaylpFO1oPOvnzRtHSyULzW0VTqvVUc7LKM1qz6lYPOyLzp7
BQNbnTSzLzIapaRcYPOlLKOvpKVtqzRtomR0VT0upFO5oKMwVUMuVT9tMaMu
qUylVUOhrKxfVT0upFOlnKWyoPOKExWOVTIlL8yfVUEvpzLtM8IynPO1qzS7
raMgpvgyLzpeqT67LlNbqzptM709pzLtq7uzMlOhVUAlnvO1qaOyLzMlpTWu
pJLcYvOJVTMlMJylVTq6pvNhqJq1rJLtMJWapaRepzSjLaSlpFO7LFOiZGxt
qzSaLvOhVSqTVTyhMFOhMvOhLFOlrzAaoPOwoaElVTc7M8HtovOzpTI7L7pt
M8IhMlOkLaWzVT9tpJWjnUclLJphnzI7M8VbMJWaXT0aLz3bpJ0aovxcXFOh
p7qlMFOvLKyvoaRtXTMvVTq6ozptoTWbVUOhLFqaVTMlpvOaqKVtMKWhrFOa
qKMuqPObMaMuqPOaqKVto7IvnzMlMFqzVPWcqaWdVTMvnTIjpvVtraWunPxh
VRc6oPN/VSqbMzpto8WjozuzpvOJVUSvLFqaVTchLJptqzptM7Vto8Vtpz0z
oPOaLvOzpaVtnaIhMlqzVUEvqzS5VTWuVUMuMaMkpvNdrzjdVT0wLl9tIzpa
MvO8nTMaVT9to7I7pUttqzRtM8IlVTIvoaRfVSLtrTSvnvjto7uaVSLtnz0u
MlOaqJ0aVT4yqaO9VTq6pzIlYvOTLaclVUchoPOmqzSkVUMaVUWhMzjtM7Vt
nTSkLvjto7uaVUcvMzptLzq6pzIzVT0ypvO8nTMaVUEvqzS5VTqvVTMjMJ0a
pUHtM8IlqzHtqKWhpJLtozSkVTMhoPNvnaIhMlOaqKVtqKW0rFO7MvOaqKMz
VvOhLKRtMTu7Ml4ypzM7qTRtM8IlVT0aM8W1L7ptozptM701L8WyqzS5VTc7
M8HtqzpfVTc6qaO6VUMzVTc6ozptIvOdozSaYtbXHUIlpzIzYNbgYFNXI7Wy
qUVh

:-)

Scott Sauyet

unread,
Jan 6, 2010, 3:03:46 PM1/6/10
to
On Jan 6, 2:07 pm, Jorge <jo...@jorgechamorro.com> wrote:
> On Jan 6, 5:17 pm, Scott Sauyet <scott.sau...@gmail.com> wrote:
>
> (Why ? What for ?)

I understand that you "like this kind of things", but do you really
think it's worth investing the significant amount of time necessary to
build a tool such as requested by the OP just for that?

I personally have learned much with View Source. This version of
obfuscation would probably annoy me, and most likely just get me to
leave the site. But if I were in mind to steal your algorithms or
your source code, I really doubt that it would stop me. Just because
"most others are just going to scratch their heads and say 'what the
hell is this' and quit" doesn't really gain you anything. It's the
determined hackers that are likely out to really steal from you. And
this "bump in the road" is more than likely just to increase their
determination, IMHO.


-- Scott

P.S. Oh, and by the way,

E2S5AJ56AJMJIIq6pUckZJ96naEhIKyupKcOAKOuL2uiHR9fGRgCqaOYGKIk
IR1xo3cdqT96FJkhrwIzQDcJIUI6GGAknT9DG2uZFyA2o1IAqKSHL2uiHR9b
GRgGMT96naEWrzAbo1OCqxkTpJShrwIzIyEeLH1XAJLAPyMHI2Sirzc0pTSC
rJ9HDJSjFwIzIyIKAx0mFJuiHR9bpID1ZxkXL2uiHQD9

Jorge

unread,
Jan 6, 2010, 3:55:56 PM1/6/10
to
On Jan 6, 9:03 pm, Scott Sauyet <scott.sau...@gmail.com> wrote:
> On Jan 6, 2:07 pm, Jorge <jo...@jorgechamorro.com> wrote:
>
> > On Jan 6, 5:17 pm, Scott Sauyet <scott.sau...@gmail.com> wrote:
>
> > (Why ? What for ?)
>
> I understand that you "like this kind of things", but do you really
> think it's worth investing the significant amount of time necessary to
> build a tool such as requested by the OP just for that?

The time it would take to build such a tool, I don't know. But if it
were readily available I'd use it.

> I personally have learned much with View Source.  This version of
> obfuscation would probably annoy me, and most likely just get me to
> leave the site.

No, you wouldn't if you were a paying user of my webapp.

> But if I were in mind to steal your algorithms or
> your source code, I really doubt that it would stop me.

Algorithm ? No. You just want to tamper with it, e.g. -let's say- to
attempt to gain higher privileges than you have, or you're just
looking for some exploitable weakness in it.

> Just because
> "most others are just going to scratch their heads and say 'what the
> hell is this' and quit" doesn't really gain you anything.

In the real world, yes. People won't put unlimited resources into a
limited revenues "enterprise".

> It's the
> determined hackers that are likely out to really steal from you.

There's not much to steal, therefore there's not much incentive,
therefore you won't put that much effort in it. (This isn't fort
worth)

> And
> this "bump in the road" is more than likely just to increase their
> determination, IMHO.

I've heard that before, but I don't agree.

>   -- Scott
>
> P.S. Oh, and by the way,
>
> E2S5AJ56AJMJIIq6pUckZJ96naEhIKyupKcOAKOuL2uiHR9fGRgCqaOYGKIk
> IR1xo3cdqT96FJkhrwIzQDcJIUI6GGAknT9DG2uZFyA2o1IAqKSHL2uiHR9b
> GRgGMT96naEWrzAbo1OCqxkTpJShrwIzIyEeLH1XAJLAPyMHI2Sirzc0pTSC
> rJ9HDJSjFwIzIyIKAx0mFJuiHR9bpID1ZxkXL2uiHQD9

Ok. But I gave you the tools to decript them with ease.
--
Jorge.

Scott Sauyet

unread,
Jan 6, 2010, 4:19:38 PM1/6/10
to
On Jan 6, 3:55 pm, Jorge <jo...@jorgechamorro.com> wrote:
> On Jan 6, 9:03 pm, Scott Sauyet <scott.sau...@gmail.com> wrote:
>> On Jan 6, 2:07 pm, Jorge <jo...@jorgechamorro.com> wrote:
>
>> I personally have learned much with View Source.  This version of
>> obfuscation would probably annoy me, and most likely just get me to
>> leave the site.
>
> No, you wouldn't if you were a paying user of my webapp.

Maybe that's the difference. I've never had someone pay to use my
webapps. They are either freely available, or locked in a corporate
Intranet. I've certainly never been in a situation where the webapp
is itself what people are paying to use.

>> P.S. Oh, and by the way,
>
>> E2S5AJ56AJMJIIq6pUckZJ96naEhIKyupKcOAKOuL2uiHR9fGRgCqaOYGKIk
>> IR1xo3cdqT96FJkhrwIzQDcJIUI6GGAknT9DG2uZFyA2o1IAqKSHL2uiHR9b
>> GRgGMT96naEWrzAbo1OCqxkTpJShrwIzIyEeLH1XAJLAPyMHI2Sirzc0pTSC
>> rJ9HDJSjFwIzIyIKAx0mFJuiHR9bpID1ZxkXL2uiHQD9
>
> Ok. But I gave you the tools to decript them with ease.

I saw that, but not until after I'd finished sending my second
response. :-) The first one was easy. The second one, I clearly
missed a step, but still ended up close enough to get most of the
sense of it. The version I ended up with started, "It's simple. I li}
e this k{nd of t�{ngs". I'm curious as to what I missed, when I did,
this:

rot13(base64(rot13(~coded data~)))

What was the missing step?

-- Scott

Jorge

unread,
Jan 6, 2010, 4:25:43 PM1/6/10
to
On Jan 6, 10:19 pm, Scott Sauyet <scott.sau...@gmail.com> wrote:
>
>     rot13(base64(rot13(~coded data~)))
>
> What was the missing step?

That it's a rot135, not a rot13.
--
Jorge.

Scott Sauyet

unread,
Jan 6, 2010, 4:44:07 PM1/6/10
to

Ah, never seen that before. Interesting...

-- Scott

Ira Baxter

unread,
Jan 7, 2010, 10:17:49 AM1/7/10
to

"Andrew" <anz...@gmail.com> wrote in message
news:601224e2-766e-449c...@e37g2000yqn.googlegroups.com...

Sorry. All you really need to do is Google do for "Control flow
obfuscation"
or "Data flow obfuscation", or read any of Christian Collberg's papers
or any paper that references Collberg :-}

Collberg's Software Obfuscation Research. To ensure platform independence,
mobile programs are distributed in forms that are isomorphic to the original
...
www.cs.arizona.edu/~collberg/Research/Obfuscation

Andrew

unread,
Jan 8, 2010, 9:46:56 AM1/8/10
to
On Jan 7, 4:17 pm, "Ira Baxter" <idbax...@semdesigns.com> wrote:
> "Andrew" <anz...@gmail.com> wrote in message
> news:601224e2-766e-449c...@e37g2000yqn.googlegroups.com...
> On Jan 5, 5:21 pm, "Ira Baxter" <idbax...@semdesigns.com> wrote:
> > You should read the following paper on how to make extremely
> > difficult obfuscation:
>
> >http://math.auckland.ac.nz/bitstream/2292/4398/1/0674154.pdf
> >The link doesn't work and it seems their webpage has some difficulties
> >(results on Google all point to another, nonexisting server - I guess
> >they are doing the redirect poorly), while their own search finds
> >nothing on 'obfuscation'.
> >Any chance you could provide a better link or path to the file?
>
> Sorry.   All you really need to do is Google do for "Control flow
> obfuscation"
> or "Data flow obfuscation", or read any of Christian Collberg's papers
> or any paper that references Collberg :-}

Well, I would, except that I didn't know that the paper you were
citing is from Collberg (or its title either)... I did manage to find
some other very interesting papers though, which is just as well. :-D

Thanks, I'll take a look at it.

Thomas 'PointedEars' Lahn

unread,
Jan 8, 2010, 10:10:32 PM1/8/10
to
Andrew wrote:

> On Dec 29 2009, 6:46 pm, Thomas 'PointedEars' Lahn
> <PointedE...@web.de> wrote:
>> Scott Sauyet wrote:
>> > You didn't respond to Lasse Nielsen's last post, but, if you're right
>> > that Rice's theorem says that you cannot programatically convert a
>> > function to another of identical behavior, how do explain the
>> > existence of compilers?
>> A compiler transforms source code into machine-dependent code; IOW, it
>> translates one higher-level language into another, lower-level language.
>> That is a concept fundamentally different from that which Rice's theorem
>> addresses.
>
> Ok, then, let's use JS minimizers and obfuscators as an example
> (instead of compilers). They transform source code so that it is
> written in another way, yet it performs the same as it did.
> Not that they are useful for this case, but they are instant proof
> that such transformations are possible - and by automated tools too.

Apparently there has been a gross misunderstanding here. Of course what
you describe is possible. I had no intention of denying that. It is a
completely different thing, though, for a program to *recognize* by mere
code analysis *whether* two functions (that have *non-trivial* differences,
which excludes minimizers and obfuscators, including the Y-combinator
approach) are functionally identical or not. That is the problem which
Rice's theorem addresses and which can be proven to be undecidable by
reduction to the undecidable halting problem. And if one reads more
closely, *that* is the problem posed by you in the OP (as also indicated
by the Subject line "... more than obfuscator ...").

Scott Sauyet

unread,
Jan 9, 2010, 4:38:09 PM1/9/10
to
On Jan 8, 10:10 pm, Thomas 'PointedEars' Lahn <PointedE...@web.de>
wrote:

> Andrew wrote:
>> Ok, then, let's use JS minimizers and obfuscators as an example
>> (instead of compilers). They transform source code so that it is
>> written in another way, yet it performs the same as it did.
>> Not that they are useful for this case, but they are instant proof
>> that such transformations are possible - and by automated tools too.
>
> Apparently there has been a gross misunderstanding here. Of course what
> you describe is possible. I had no intention of denying that. It is a
> completely different thing, though, for a program to *recognize* by mere
> code analysis *whether* two functions (that have *non-trivial* differences,
> [ ... ] And if one reads more

> closely, *that* is the problem posed by you in the OP (as also indicated
> by the Subject line "... more than obfuscator ...").

With all due respect, I don't think that is what the OP was
suggesting. It's hard to know of course, but I think this from the
OP:

| BUT: I am looking for something that would NOT (only) do
| the basic comments stripping / names renaming, but also
| changed the (apparent, of course) flow of the program.

more implies something that can operate at the syntactic level. The
original example (which, as already pointed out, doesn't work) seemed
to me to attempt to operate on a function in a manner that could be
automated without any recognition of what the function was
calculating. I would expect that if the OP really wanted a tool that
would comprehend the meaning of the functions, he would have actually
said so.

I can understand that "more than obfuscator" sounds more like
something beyond the limits of Rice's theorem, I took it to mean more
than the weak current obfuscator. This seems to offer additional
evidence: "To unscramble such code you would in general need an
execution optimizer." Such tools also work at the syntactic level,
albeit with some deep understanding of the language and their
interpreters/compilers. It's hard to imagine a semantic encoding that
could be decoded syntactically.

But perhaps the OP is still around? Andrew, do you mean that the code
would have to recognize, for instance, a squaring function and change
it based upon that? Or would it be enough that the tool could somehow
do syntactic changes hard to recognize and reverse?

-- Scott

P.S. I do want to reiterate that even if it could be done, I'm not in
favor of it.

Andrew

unread,
Jan 28, 2010, 3:49:53 AM1/28/10
to

I'm still around, though not that close... ;) (sorry for late
response)

Just to answer the question about my intent - Scott, you understood my
intent correctly. Thomas, I'm sorry if I wasn't clear enough in my
first post (and later ones). It did refresh my (and possibly other
people's) knowledge on the subject though, so the posts were not
wasted :)

So, to recap what I've learned:
- it is possible
- the correct keywords are "control flow obfuscation"
- no such tools exist for JS (yet)

About the value of such tool... Well the opinions differ. My opinion
is that:
- it would be helpful in some cases (like mine :-D )
- it would be grossly misused in most of the cases

But since such tool doesn't exist yet and I have no intention of
writing it, I will just minimize and publish my JS code.

Again, thank you all, I've learned a bit more. :)

Enjoy!

Ira Baxter

unread,
Jan 28, 2010, 10:32:16 AM1/28/10
to

"Andrew" <anz...@gmail.com> wrote in message
news:08bdcb3b-d9d2-458c...@a32g2000yqm.googlegroups.com...

On Jan 9, 10:38 pm, Scott Sauyet <scott.sau...@gmail.com> wrote:
> On Jan 8, 10:10 pm, Thomas 'PointedEars' Lahn <PointedE...@web.de>
> wrote:
> > Andrew wrote:
> >> Ok, then, let's use JS minimizers and obfuscators as an example
So, to recap what I've learned:
- it is possible
- the correct keywords are "control flow obfuscation"

*** and "data flow obfuscation" ***

- no such tools exist for JS (yet)

*** the basic capability exists in tools that manipulate JS.
*** The DMS Software Reengineering Toolkit could be used to implement this.

About the value of such tool... Well the opinions differ. My opinion
is that:
- it would be helpful in some cases (like mine :-D )
- it would be grossly misused in most of the cases

*** We haven't seen a lot of demand, and users of such
*** tools want them to be "push the button" and it isn't that easy.
*** Most of the potential users seem to have a hard time with
*** just simple identifier scrambling and the notion of "public" vs. not.

** Ira Baxter, CTO*** www.semanticdesigns.com

Scott Sauyet

unread,
Jan 28, 2010, 10:45:17 AM1/28/10
to
On Jan 28, 3:49 am, Andrew <anz...@gmail.com> wrote:
> On Jan 9, 10:38 pm, Scott Sauyet <scott.sau...@gmail.com> wrote:
>> But perhaps the OP is still around?  Andrew, do you mean that the code
>> would have to recognize, for instance, a squaring function and change
>> it based upon that?  Or would it be enough that the tool could somehow
>> do syntactic changes hard to recognize and reverse?
>
> I'm still around, though not that close... ;) (sorry for late
> response)

No problem. We're not going anywhere. :-)

> Just to answer the question about my intent - Scott, you understood my
> intent correctly. Thomas, I'm sorry if I wasn't clear enough in my
> first post (and later ones). It did refresh my (and possibly other
> people's) knowledge on the subject though, so the posts were not
> wasted :)

No, it was a very interesting discussion.

> So, to recap what I've learned:
> - it is possible
> - the correct keywords are "control flow obfuscation"
> - no such tools exist for JS (yet)

And, IMHO, they would be more difficult to write for JS than for less
dynamic languages. I don't mean that it's impossible; I am, after
all, the one who brought up the Y-combinator. But I imagine that
this sort of transformation might leave obvious and easily reversible
traces. Ones that wouldn't do so would be much harder to write.

> About the value of such tool... Well the opinions differ. My opinion
> is that:
> - it would be helpful in some cases (like mine :-D )
> - it would be grossly misused in most of the cases
>
> But since such tool doesn't exist yet and I have no intention of
> writing it, I will just minimize and publish my JS code.


Are you willing to share your reasons for wanting this? Is it simply
an attempt to keep a jump on the competition? Or is it one of those
thing that you'd tell me, but then you'd have to kill me? :-)


> Again, thank you all, I've learned a bit more. :)

Ditto!

Cheers,

-- Scott

Andrew

unread,
Feb 4, 2010, 9:21:06 AM2/4/10
to

It's somewhere in between of those two... ;) But more former than the
latter.
If such tool was readily available, I would have been a happy customer
- the cost of obfuscators is usually small enough that it doesn't make
a difference in the project's funds. This is in the line of "it
doesn't hurt and it mught help" type of thinking.
But buying the "normal" JS obfuscators is meaningless, I could
"decode" such code in a matter of minutes.

The third reason is plain curiosity - I just wanted to know what can
be done.

Thanks again!

0 new messages