Hacker Newsnew | past | comments | ask | show | jobs | submit | ollyfg's commentslogin

I probably deserve to get downvoted to oblivion for this but... I've deployed JSFuck in production!

We wanted to obfuscate this bit of code, to make life just a little bit harder for reverse engineers. We made this huge function where we pretty much passed in all our application state, and it would run this JSFuck code, and spit out a token. We even made a few tweaks to the code so that you couldn't just reverse it back into JS with something like https://enkhee-osiris.github.io/Decoder-JSFuck/.

Performance was surprisingly alright, and it has never hit an environment where it couldn't execute. All in all, a fun few hours setting it up, and I haven't had to touch it since!


makes me sad to hear that :( I will say, as a reverse engineer, that javascript minifiers like closure compiler will optimize almost all obfuscation out, and the rest you can usually translate to a form which it can understand and then it will do the rest.

The effect of obfuscation is not what you expect. It seems like it moves the whole difficulty up, but it only moves up the floor. By doing so it tends to remove all the signals that would warn non-experts of security issues. Remove the obfuscation and then you have all the catastrophic security issues that have accumulated in there like treasures in an egyptian king's tomb https://zemnmez.medium.com/how-to-hack-the-uk-tax-system-i-g...


Makes me think of what might deter a reverse engineer and then this most awesome youtube talk on psychological warfare by Chris Domas

https://youtu.be/HlUe0TUHOIc

It's so good.


I'm curious: can you can undo the obfuscation of JScrambler and Obfuscator.io easily? Some time ago I tried to run both through Closure Compiler, but it was way harder than I thought would be.


JScrambler I actually did de-obfuscate to bypass some very significant bot detection a few years ago, but it took a bit more doing -- it uses ES6 features IIRC so I had to transpile it down to ES5 via babel first, but it worked OK after that.

has a pretty good crack at obfuscator.io, too: https://closure-compiler.appspot.com/home#code%3D%252F%252F%...

That's the example from the site. "console.log('Hello world')" gets deobfuscated to "console[a(482)]("Hello World!");"


> That's the example from the site. "console.log('Hello world')" gets deobfuscated to "console[a(482)]("Hello World!");"

That does not look deobfuscated to me.


Anyone familiar with JS is going to have some really good guesses at what a(482) is in this case.

And, even if you don't, you can always call a(482)


Yes, but "obfuscated" means "To make so confused or opaque as to be difficult to perceive or understand". That's obfuscated, not deobfuscated.


Is that difficult? Harder, but still quite easy.


My point was that the GP seems to have mixed the words "obfuscate" and "deobfuscate".


To clarify, that's what happens once you pass it through the obfuscation and THEN closure compiler. If you click the link you will see the obfuscation is much more complex


Oh, then I misunderstood and everyone should ignore this whole thread :P


Obfuscation is like locking your front door. It won't stop anyone who is dedicated, but it might stop someone who isn't.


While I think itcs bad to use obfuscation to hide security holes, I do think obfuscation has it's uses. If there's reasons to make data private, then there's reasons to make execution private as well. Not to mention, it was recently proved that indistinguishable obfuscation is possible, so I'm not sure how useful de-obfuscation tools will be in the future


But you don't make data private by obfuscating it and then passing it to people you don't trust.

You make data private by not giving it to people you don't trust, or by encrypting it and not giving the key to people you don't trust.


By "making data private" I meant encryption


Really enjoyed that blog post, thanks for linking it! How long would you say actually finding those two issues took? The attack surface must've been fairly large, but I guess intuition helps.


If I recall, the whole thing took about 6 hours


Do you consider Google Closure sufficiently good obfuscation?


I think closure compiler's 'obfuscation' is an incidental part of its minification passes.


Got it. Thank you.

I've been using the Google Closure compiler for many years with advanced and every time I look at the code output I'm like "there's no way in a 100 years I would be able to de-obfuscate back to my own code to a great extent". But I don't specialize in reverse engineering, so I might be missing something big.


Expecting obfuscation to increase security is a fool's errand. However expecting it to cut down on re-use of your code then it will no doubt work.


personally, I find the code it outputs to be easier to understand often than the source because it simplifies a lot of stuff into the most abstract logic. I think it takes some getting used to for your brain to connect those pieces, though


Fair enough, thank you.

I guess ultra-shortening the names into a,b,c,d,e, etc makes it superficially hard to understand what's going on but I agree on your point about abstract logic.


Thanks for the link to that blog post, really interesting!


I understand the frustration, but as someone having to debug browser bugs with JavaScript edge cases, minified (and in this case ultra-obfuscated) JS is hell on earth to untangle and I wish people wouldn't.


Just making sure - you're using js source maps, right? The minifaction should be adding significant pain in your debugging process.



That blog is horrific on mobile


IME, code on prod rarely ships with a sourcemap. and as far as i can tell, GP is talking about other people's minified code, not something where they control the build process


I think I might've actually analysed the code you're describing.

We even made a few tweaks to the code so that you couldn't just reverse it back into JS

This is why a lot of us keep our tools private... an old tradition of the cracking scene going back decades to the 80s. Think of things like IDA/Hexrays and Ghidra, then realise the most prolific crackers had similar private tools they had written many years before those appeared.


>This is why a lot of us keep our tools private

How ironic, that you want to open up other peoples code but keep your own hidden.


Not really ironic or related. The privacy here is, well, keeping the tools entirely private -- no distribution or highly limited distribution, not obscuring their function.

Irony would be applying obfuscation or other DRM protection techniques to tools intended to de-obfuscate/reverse engineer which are then distributed/sold. This is fairly common in commercial reverse engineering solutions, although I don't think the irony of the cat and mouse game is lost on the authors in that case...


why not - after all, none of the open source licenses say that you must actually distribute the program, they only say that you should also include the source code if doing so.


Different motives. Think of it like encryption: when someone finds a weakness in a cypher people will generally move onto a new cypher that’s harder to crack. The difference here is the purpose of writing those tools isn’t to improve security, it’s to break code open. So keeping these tools hidden keeps them effective.


The world is a complex place. It's not just open source vs closed source.


But once better tools have been published, why not show what you did?


Did you have a legitimate reason to make things harder for reverse engineers?


Why are you reverse engineering my code in the first place?


Because you gave it to me to run it. I want to know what is it exactly that I'm running.

Also, why do you mind me doing that?


No, I didn't give it to you to run. It's explained below if you read the whole thread.


Because it's broken for my usecase, and I need to do something slightly different on the webpage


You shouldn't have access to it -- it's on my private servers doing stuff for me. How did you get it?

I think the problem with this thread is people think I am writing browser code, or code that is going to be shared on GitHub.

I am not.

Also I'm only half joking as I've indicated with the "/s" below.


> You shouldn't have access to it -- it's on my private servers doing stuff for me. How did you get it?

Seems like the logical solution would be to restrict access to it then, rather than obfuscate it making it harder for yourself to maintain. But hey, you do you.


At the bottom of the thread I explain the intention is to protect against unauthorized access.

I also wouldn't obviously edit the obfuscated production code, so it wouldn't really be a problem.


> You shouldn't have access to it -- it's on my private servers doing stuff for me. How did you get it?

Well thanks for chiming in about a completely unrelated topic from website javascript. My comment wasn't getting downvoted until your slapfight with oauea blew up.


Specifically from the web page:

"It does not depend on a browser, so you can even run it on Node.js."


That wasn't a top level question though, it was a question to a commenter saying "We wanted to obfuscate this bit of code, to make life just a little bit harder for reverse engineers." That you obfuscate code nobody other than you can even access is completely irrelevant as a reply to that question.


So then you should ignore the entire thread and move on. Why are you wasting time on this?


To figure out what it's doing, obviously.


Please STOP that.


I'll make you a promise: if your code never ends up on my machine, I will never try to reverse it.

Otherwise, all bets are off.


Don't request it then :p


If it's not part of any service that's marketed to me, I won't. However, if some vendor wants to run code on my machine, I _will_ be inspecting it.


Why would I put it on YOUR machine? It's my code. Don't hack my servers, or all bets are off. /s


JS is often (but not always) transmitted from the server to execute on the client machine


You've never heard of NodeJS?


(but not always) <~ this includes nodejs


Friend, I'd love to come to an agreement that your code won't end up on my machine. I'm buying beers when we get together.


No thanks. Anything you submit to run on my machine is fair play :-)


This code should never run on your machine. :P


Then why are you obfuscating it or even worried about people deobfuscating it? This thread is about Javascript.


Dude, I write financial applications in Node. Node IS javascript.

These applications run on the back end. Some of the API facing VMs have been attacked and so to be honest I've configured them so that if someone did get access to them, they wouldn't find much. Maybe just some API keys I can invalidate. Although I probably won't do it -- an obfuscator like this could be very handy here.


Did you give a try of Deno. This is a JavaScript runtime but it produce a single binary. This would make sense in your case because it can be harder to inspect it.


You must have changed it a lot, this seems to produces 100s of kb of obfuscate code for with just a tiny input.


I think you ultimately need to do something like Function(code)() in JSFuck, so it is always possible to remove the final function call and get the `code` directly.


Interesting. I can definitely relate. As an author of a proprietary application written in web technologies, it's easy to be envious of compiled languages.

This is my recipe for minification:

1. Apply a convention where all class properties and methods have to end with a trailing underscore (it's trivial to make an Eslint rule to enforce it)

2. Use 2 minification tools in following order: Closure Compiler (simple optimizations mode), then Terser for best output.

3. Configure Terser mangle.properties.regex: /_$/

4. If it's a desktop app, use Bytenode for Node.js processes (cannot be used for the renderer)


A further obfuscation you could also compress it and have the app unpack itself.

eJztVUESwyAIfAs3GJ60w/+/UZKiUUwzztT20OZiwgIbWJXAwARTmMAX02qRr0o9Vu02xRmwgKUPTzHv0weu8bGtZFhKyKSnTK0Z/parAJ/VI5WyXp7Uo/HYNc3qNchzKWBACnpCK3uj3N1Quvs6qCSJ4Gvah+++VT9/q3AlWLH5Pg3/cRqO94lR5SM5T6rDKSelDOUKC0+EzQ36l5N/zR7lDqti9Xjsj3U71f4AduQBlR9rUg==


Talk about security by obscurity!


[flagged]


Please don't cross into personal attack on HN.

https://news.ycombinator.com/newsguidelines.html


If you can use the decoder, the reverse engineers will use the same, no?


For someone to reverse your code, all they need to do is run it through this.

  https://enkhee-osiris.github.io/Decoder-JSFuck/


I think you missed this sentence from the comment you're replying to:

> We even made a few tweaks to the code so that you couldn't just reverse it back into JS with something like https://enkhee-osiris.github.io/Decoder-JSFuck/.


Not sure if it's what you mean by blank (not a big keyboard geek, but I just got a Moonlander), but when you buy it there's an option for all of the keys to have "-" on them, so it's effectively blank?


I may be misunderstanding what you're asking, but the ErgoDox EZ has two different keycap shapes.

The printed keys are all the same shape and can be moved around as one remaps the keys. However, this results in a flat keyboard. You can get the same effect by buying another set of keycaps from a keycap company.

The blank keys are sculpted, so each key is unique to it's position or a set of positions. This makes reaching keys much easier from the default position, but makes learning the keyboard harder.


I had started down the path of trying to buy replacement keys, ideally blank but with some sort of a clear spot so the keyboard lights can shine through. That was rare enough, and I guess maybe in the end I might just want clear keycaps for the lights. But there's a whole set of lingo in the keycaps that I felt like I had to understand to stand a chance of getting the correct set of keycaps. There wasn't just a "Here's a ErgoDox EZ caps set..."


I just tried buying and didn't see an option beyond color and keycaps. I had even mailed them maybe a month ago just to double check, because for my ErgoDox EZ they were able to do a custom order with the lit keys but black keycaps. They had said they are still looking at doing an "all -" blank set, but didn't have it available yet.

How do you like the Moonlander? I really love my ErgoDox, but the Moonlander looks nice.


Wow! How have I not heard of frida? This should make my normal process much simpler!

1) Decompile App -> smali

2) Decompile App -> Java (non-reversible, but easier to read)

3) Search the app for certificate pinning code (check for network_security.xml or grep for OKHttp pinning functions)

4) Find the code I just found in java, in the smali version

5) Remove the pinning code

6) Recompile smali -> apk

7) Fix whatever was causing the smail not to recompile

8) Recompile again

9) Pray

10) Install on device

11) Run app (that hopefully doesn't crash)

12) Pipe connection through Charles proxy

13) Read api calls!

I'll definitely give it a go.

In general I think there are nowhere near enough resources on decompilation, particularly on a purportedly "open" platform like Android. Really looking forward on the rest of the tutorial coming online.


As an alternative, you could use the XPosed framework. It basically lets you overwrite App and System methods and classes by installing a small module. No need to modify your target apk. So you can just return true from the method that checks if the correct certificate is in use.


XposedMod is amazing but you could override methods with Frida, as well. Just that Frida works both with or without having to root the device.


"there are nowhere near enough resources on decompilation, particularly on a purportedly "open" platform like Android."

Most apps are definitely not 'open' and unfortunately most of 'reverse engineering' has nefarious intentions.

Once one has had key code stolen from them, it changes one's perspective a little.


Unless your APK is internal and not distributed outside a small circle, assume your code has been reverse engineered.

Surely if you're running something that has to be that "closed", most of the key code is server side and the client is just calling APIs.

Reverse engineers are not your enemy.


"Unless your APK is internal and not distributed outside a small circle, assume your code has been reverse engineered."

Of course, but doesn't obviate the illegality of stealing protected code.

"Reverse engineers are not your enemy."

Yes, many of them are.

Many of these resources and individuals are involved in illegal and immoral acts around stealing code and IP, and justify it to themselves on some kind of skewed logic.

Nobody really cares that folks are hacking code for fun, and nobody cares that people would use resources for this purpose. This is fine and possibly helpful.

But IP theft is a big deal, and it's very damaging.

"Surely if you're running something that has to be that "closed", most of the key code is server side and the client is just calling APIs"

Unfortunately, this isn't possible in a variety of cases, especially new and upcoming scenarios that require AI to be 'on device'. There are many other such scenarios.

It's very oppressive to a major class of innovation - particularly to those who've worked very hard to assemble something exceptional and useful.


Are you suggesting that reverse engineering resources not be made available because you feel it will lead to people stealing code?


Interesting!

I've switched to using Ian's knot, and have found it to be both faster to tie and easier to set up. I think once you work out how to 'pick up' the laces in the right way, so that they are already in the correct starting position, it gets a lot faster/simpler to think about.

Of course, I haven't been in your shoes - my laces are all the round type and I haven't tried it with flat ones.

To each their own!


I like flat laces a lot because they seem to distribute the force a lot better than round styles. I like my shoes to be fairly minimalist, I don't like overly padded or heavy shoes, and round styles seem to put a lot more pressure on the top of my foot.

The oval style with the sharp edges has a lot of the benefits of the flat style, but is more universally compatible. The flat ones don't always move well in round eyelets, they work better with loops in my experience.

The completely flat style doesn't tie well if one of the laces is twisted though. I think it's a great option for athletic shoes though, where you are more likely to care about a particular level of give, etc, and when you don't want your shoes to become untied. The round style is cheaper, and if you don't notice the difference it's probably a more versatile shoelace.

Plus you can do fancy knots with the round style.


Looks good! One feature that would definitely get me using this for personal projects is the ability to add/customise axis. You might already have this, but I didn't see it in any of your examples, so if this is present, please advertise it!

My general reaction when seeing a chart without axis is "pretty, but I can't see what it means", where as with decent labelled axis I can dig into it and look at data points, and come to my own conclusions about the data.

Still, this is a useful service that could make life much easier - keep at it!


EDIT: HN is doing some escaping to my example URL, so I adjusted it a little below.

Author here, thanks for the feedback!

My default use case was to use these images as background-images (via CSS) in dashboard widgets that show an accurate trend for how data has changed over time. Therefore my defaults were to hide to x and y-axis and make the chart margin 0 to fit in the widget and look "nice" across the entire thing.

But if you are or become familiar with the Highcharts chart config options, you can update any option you want for the axis via the `raw` param (see more detailed info on the params in github: https://github.com/whatl3y/restcharts). One thing you could do to one of the simple charts provided on the landing page to show the axes is override the default margin values (which is margin: [0, 0, 0, 0]) and make the x-axis and y-axis visible like so:

where [raw]={"xAxis":{"visible":true},"yAxis":{"visible":true},"chart":{"margin":null}}

your URL would become

https://localhost/chart/line?data=5,1,2,9,8,3,0,0,4&raw=[raw...

You can obviously continue to add config to adjust the language on the axes among other things. I realize this could get a little verbose quick, but again the idea was to make a simple, quick view of data, even though you could technically get as complicated as you want with the `raw` param.


Update: You can now see examples with axes shown in the Advanced Section: https://www.restcharts.com/#Advanced%20Configuration


Would you care to share the link to that live stream? Sounds fun ;)



Have you tried openshot[1]? I haven't played much with it recently, but when it came out it was the most stable, simple video editor for linux.

[1] http://openshot.org/


No. Wow, a lot of great suggestions here. I need to test stuff now :)


Middle click (if you have it) gets around this!


If there is one thing I've learned from university, it's this. Keeping units makes your writing messier and longer, but when it comes to checking they are absolutely invaluable. Your equation to give you volumetric flow gave you (kg/s)? Well density is (kg/m^3) so just divide your answer by density! (this is a problem my friend was having just yesterday)


I think the problem is they don't teach the same units everywhere in the world.

I grew up in Australia with SI units I do a lot of work with Fluid/Thermodynamic calcs. I have a bunch of reference values in my head. I know 1 Atmosphere is ~101.3 kPa, I know speed of sound in dry air is ~330 m/s I know how much energy it takes to raise the temperature of various substances. I know the densities of common materials in my head. All of that helps me sanity check calculations - at a glance I can see things 'this fan is producing too much suction, not possible' or 'There is not enough input energy to see a temperature rise that high' things like that.

I have no idea about any of the non SI units. I couldn't tell you how long a "yard" is or how heavy a "pound" is usually it is fine but occasionally I come across numbers in technical papers or datasheets or similar with stuff in wacky units - PSI, BTU and Fahrenheit are the worst offenders when I have to deal with them it just blue screens my mental models. I see those units so infrequently I have no concept of what a 'reasonable' value expressed in those units looks like. I imagine people who don't work in SI units everyday hit the same difficulties in reverse.


This is interesting because there's actually a unit-agnostic way of doing units more generally... it's "dimensional" rather than unit-based. So regardless of the base units you'll do "length" (which works for all three axes: length, depth, breadth) and "mass" (which works for kg, pounds, whatever) and "acceleration", "force", etc.

Obviously this is slightly more lax and perhaps error-prone than your standard m/s or m/(s^2), etc., but it's one of the lamentably few things computers can do well!

EDIT: ... and I should elaborate: In some sub-fields of Physics they usually go even further and just re-normalize everything to units of 1, so that e.g. the speed of light is c is 1. At that point it's really just about convenience since sqrt(1) = 1, and 1^x = 1, etc. (Lorentz Transformation.)


I believe that bigger_cheese is lamenting his or her inability to do numerical sanity checking in other units. (This loss of numerical information is, perhaps, what you meant by saying that the unit-agnostic approach is 'more lax'.)

For example, if I am looking for a force and I get an answer of 1000 lbs, then dimensional analysis tells me that at least I got a force; but, if my intuition tells me only that the actual force is on the order of magnitude of 1000 N, then I don't know whether my actual answer is way too big, way too small, or about right, unless I know how to convert between Newtons and pounds.

Incidentally, while "units of 1" make correct calculations easy, I think that they are a bad idea precisely because they subvert unit checking; it's hard to know just by looking that 1 + 1 is 1 speed of light + 1 light-year, and hence dimensionally inconsistent.

(Even keeping all SI units can miss some important distinctions; for example, nothing about their SI units (inverse time) allows us to distinguish angular frequency (https://en.wikipedia.org/wiki/Angular_frequency) from temporal frequency (https://en.wikipedia.org/wiki/Frequency), and yet much woe accrues to he or she who does not distinguish radians/time from cycles/time!)


Oh, yes, re-read it and right you are.


> PSI, BTU and Fahrenheit are the worst offenders

With Fahrenheit perhaps the worst of the worst (scum de la scum?), because at least you have an intuitive idea of the meaning of 0 PSI and 0 BTU.


To automate this process, check out Frink[0], which takes unit calculations to the obsessive limit.

[0] https://futureboy.us/frinkdocs/


My middle school physics teacher taught us to build those formulas by reverse-engineering the units. This was before we had done enough algebra to know what we're doing so we used triangle diagrams, but boy was it the best thing I ever learned.

Don't understand what something is? Just look at the unit. It tells you!


What’s a triangle diagram?


     a
    b c
encodes

  a = b * c
  c = a / b
  b = a / c


This reminds me of the way Big Brother is working on a new language that doesn't have words for things you're not allowed to do - if there's no word for it, how can you think about doing it?


Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: