After using this obfuscation above there appears to be an extreme performance dip using Mirrors. Any idea why? Anyone else encounter this?
obfuscation will de-optimise your critical loop code and turn it into slow performing junk code. doing this will threejs, not good!
it wards off some lazy people but if someone really wants your code they get it. the obfuscator is oss and can be reversed, there are even projects out there called “un-obfuscator”.
btw this code:
var variable1 = '5' - 3
var variable2 = '5' + 3
var variable3 = '5' + -'2'
var variable4 = ['10', '10', '10', '10', '10'].map(parseInt)
var variable5 = 'foo ' + 1 + 1
console.log(variable1)
console.log(variable2)
console.log(variable3)
console.log(variable4)
console.log(variable5)
turns into this, it’s no wonder it runs slower
var _0x9947 = [
'map',
'log',
'foo\x20',
'bvmqO',
'133039ViRMWR',
'xPfLC',
'ytpdx',
'1243717qSZCyh',
'2|7|4|6|9|',
'1ErtbCr',
'1608314VKvthn',
'1ZRaFKN',
'XBoAA',
'423266kQOYHV',
'3|0|5|8|1',
'235064xPNdKe',
'13RUDZfG',
'157gNPQGm',
'1639212MvnHZL',
'rDjOa',
'iBHph',
'9926iRHoRl',
'split',
]
function _0x33e4(_0x1809b5, _0x37ef6e) {
return (
(_0x33e4 = function (_0x338a69, _0x39ad79) {
_0x338a69 = _0x338a69 - (0x1939 + -0xf * 0x1f3 + 0x1 * 0x469)
var _0x2b223a = _0x9947[_0x338a69]
return _0x2b223a
}),
_0x33e4(_0x1809b5, _0x37ef6e)
)
}
;(function (_0x431d87, _0x156c7f) {
var _0x10cf6e = _0x33e4
while (!![]) {
try {
var _0x330ad1 =
-parseInt(_0x10cf6e(0x6c)) * -parseInt(_0x10cf6e(0x6d)) +
-parseInt(_0x10cf6e(0x74)) * -parseInt(_0x10cf6e(0x78)) +
parseInt(_0x10cf6e(0x6a)) +
-parseInt(_0x10cf6e(0x70)) +
parseInt(_0x10cf6e(0x6e)) * -parseInt(_0x10cf6e(0x75)) +
parseInt(_0x10cf6e(0x72)) +
-parseInt(_0x10cf6e(0x67)) * parseInt(_0x10cf6e(0x73))
if (_0x330ad1 === _0x156c7f) break
else _0x431d87['push'](_0x431d87['shift']())
} catch (_0x9f878) {
_0x431d87['push'](_0x431d87['shift']())
}
}
})(_0x9947, -0xb6270 + 0x4dfd2 * 0x2 + 0x75460 * 0x2),
(function () {
var _0x1f346d = _0x33e4,
_0x860db8 = {
ytpdx: _0x1f346d(0x6b) + _0x1f346d(0x71),
bvmqO: function (_0x560787, _0x519b9e) {
return _0x560787 - _0x519b9e
},
rDjOa: function (_0x4501fe, _0x2b07a3) {
return _0x4501fe + _0x2b07a3
},
xPfLC: function (_0x5f3c9b, _0x434936) {
return _0x5f3c9b + _0x434936
},
XBoAA: function (_0x535b8a, _0x42eef4) {
return _0x535b8a + _0x42eef4
},
iBHph: _0x1f346d(0x65),
},
_0x346c55 = _0x860db8[_0x1f346d(0x69)][_0x1f346d(0x79)]('|'),
_0x3bf817 = 0x4bb * 0x1 + 0x801 + -0xcbc
while (!![]) {
switch (_0x346c55[_0x3bf817++]) {
case '0':
console[_0x1f346d(0x7b)](_0x4c96d8)
continue
case '1':
console[_0x1f346d(0x7b)](_0x101028)
continue
case '2':
var _0x65977d = _0x860db8[_0x1f346d(0x66)]('5', -0x586 + -0x2195 + -0x6 * -0x685)
continue
case '3':
console[_0x1f346d(0x7b)](_0x65977d)
continue
case '4':
var _0x56d39b = _0x860db8[_0x1f346d(0x76)]('5', -'2')
continue
case '5':
console[_0x1f346d(0x7b)](_0x56d39b)
continue
case '6':
var _0x544285 = ['10', '10', '10', '10', '10'][_0x1f346d(0x7a)](parseInt)
continue
case '7':
var _0x4c96d8 = _0x860db8[_0x1f346d(0x68)]('5', 0x622 * -0x6 + 0x4a * 0x3 + 0x1 * 0x23f1)
continue
case '8':
console[_0x1f346d(0x7b)](_0x544285)
continue
case '9':
var _0x101028 = _0x860db8[_0x1f346d(0x6f)](
_0x860db8[_0x1f346d(0x6f)](_0x860db8[_0x1f346d(0x77)], 0x6fb * 0x5 + 0x1ebf * 0x1 + -0x41a5),
0x209 * 0xa + 0x1314 + -0x276d
)
continue
}
break
}
})()
I get that obfuscation can be detrimental to performance and I agree that it is a bit ott but are you saying you can deobfuscate the obfuscated code you’ve shared to read as the original you posted above it? I’ve tried with a few online tools with little to no improvement of readability, definitely nothing like the original code snippet you posted…
@FuzzyWobble you can try setting “splitStrings” to false, it’s likely that there’s shaders defined as strings in the mirror
class which are all going to be broken into smaller nightmare chunks, it’s worth playing around with the settings of the obfuscator you’re using, you can also try only obfuscating certain important parts of your code too maybe…
@drcmda I think obfuscation can be a very important tool, especially if working and sharing code that might be contractual, it can add a level of security so working environments can be experienced and navigated until the contract is fulfilled, at which point the source can be released… Its definitely not optimal or something you’d want to push to deployment builds though unless very subtle settings are used which simply shorten variable and function names
here: https://deobfuscate.relative.im
so easy, now i have your code.
var _0x65977d = '5' - 3
var _0x4c96d8 = '5' + 3
var _0x56d39b = '5' + -'2'
var _0x544285 = ['10', '10', '10', '10', '10'].map(parseInt)
var _0x101028 = 'foo ' + 1 + 1
console.log(_0x65977d)
console.log(_0x4c96d8)
console.log(_0x56d39b)
console.log(_0x544285)
console.log(_0x101028)
at best obfuscation stops casuals. and if that tool above didn’t exist, since the obfuscator is open source really all you’d need to do is reverse it. an afternoon of work. even if the obfuscator is proprietory, AI will have a field day with this.
I ran the deobfuscator on some previously obfuscated code and it outputs this:
So yes it definitely deobfuscates the code very well, but the final output is still quite annoying to make sense of with the variable names turned to nonsense, so I guess it’s better than nothing…
imo not annoying at all. code’s there. add something that re-establishes the variable names and it may be better then the original:
it is what it is, if a 100x negative performance impact is worth it so that a casual won’t be able to read it, go for it.
Interesting, I tried with one of my projects and got the following result…
Starting deobfuscation with timeout of 2 minutes
Deobfuscation error! SyntaxError: 'import' and 'export' may appear only with 'sourceType: module' (1:1449)
looks like you have to use the cli tool directly, it has more options. but im not familiar with it, was just the first thing i found.
The goal of obfuscators is to obfuscate, i.e. to deform the code to a point it is incomprehensible by humans, but still keep it working. The cost for this is often performance. In most cases this lost of performance is not noticeable, but is some time-critical and performance-critical situations (as in 3D graphics) obfuscation has a pretty negative impact. For example, I’ve seen obfuscators that decompose constants and function calls and then composing them back in real-time. This kills all possible optimizations.
No, when I meet obfuscated code, it is usually in some simple cases. And I have never obfuscated my own code too. In the past I thought of doing it – it was for a 3D interactive student assessment tool. I didn’t want the students to easily see the code. But then I told myself, hey, if they look in the source, they will more than simply studying for the exam. So I just minified the source, keeping the actual (and long) names of variables… + I also gave the students the original source code. And I have never felt sorry for this.
@drcmda thanks for your brutally passive agressive help
haha, that’s me in a nutshell
but i do hope it helped to at least get another perspective. in a company i’ve worked for we got our obfuscated code stolen. there is very little safety in that.
@drcmda I just realised something that made my eyes water a little on seeing the result
…the result…
Original…
Obfuscate the following code so it is painfully difficult to decript for yourself and humans....
// create a camera
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
// position the camera to the right of the cube
camera.position.x = 1;
camera.lookAt(new THREE.Vector3(0, 0, 0));
// render the scene
renderer.render(scene, camera);
// change the camera position to the top of the cube
camera.position.y = 1;
camera.lookAt(new THREE.Vector3(0, 0, 0));
// render the scene again
renderer.render(scene, camera);
The obfuscation…
(function(){var 𝓯=["P","e","r","s","p","e","c","t","i","v","e","C","a","m","a"];var ₥=𝓯.join("")+"mera";var 🧿=window["in"+"ne"+"rW"+"idt"+"h"],🐉=window["inn"+"erHe"+"ight"],∑=0.1,ℵ=1000;var ✡=function(a,b,c){return new a(b,c,∑,ℵ)};var 🎥=new (THREE[₥])(75,🧿/🐉,∑,ℵ);var 🧩="pos"+"it"+"ion",📏=🎥[🧩];📏.x=1;var 🌟=function(a,b,c){return new a(b,c,0)};var 🔭="lo"+"okA"+"t";🎥[🔭](new (THREE["Vec"+"tor"+"3"])(0,0,0));var 🧊=function(a,b){a.render(b,🎥)};var 🧚="rend"+"er";renderer[🧚](scene,🎥);📏.y=1;🎥[🔭](🌟(THREE["Vec"+"tor"+"3"],0,0));renderer[🧚](scene,🎥)})();
The deobfuscation of the above encryption…
(function(){
// Define parts of the PerspectiveCamera class name
var perspectiveArray = ["P", "e", "r", "s", "p", "e", "c", "t", "i", "v", "e", "C", "a", "m", "e", "r", "a"];
var cameraType = perspectiveArray.join(""); // Result: "PerspectiveCamera"
// Window dimensions for aspect ratio
var windowWidth = window.innerWidth;
var windowHeight = window.innerHeight;
// Camera parameters: field of view, near clipping plane, far clipping plane
var fov = 75;
var nearPlane = 0.1;
var farPlane = 1000;
// Create a perspective camera
var createCamera = function(THREE, fov, aspectRatio, near, far) {
return new THREE.PerspectiveCamera(fov, aspectRatio, near, far);
};
// Initialize camera
var camera = new (THREE[cameraType])(fov, windowWidth / windowHeight, nearPlane, farPlane);
// Set camera position
var positionKey = "position";
var cameraPosition = camera[positionKey];
cameraPosition.x = 1;
cameraPosition.y = 1;
// Look at a point (0, 0, 0) in the scene
var lookAtKey = "lookAt";
camera[lookAtKey](new THREE.Vector3(0, 0, 0));
// Render function that uses a scene and a camera
var renderScene = function(renderer, scene) {
renderer.render(scene, camera);
};
// Initial render call
renderer.render(scene, camera);
// Update lookAt and re-render
camera[lookAtKey](new THREE.Vector3(0, 0, 0));
renderer.render(scene, camera);
})();
EDIT: merely prompting “more” a few times gives the following …
(function(){
var 👽=function(x){return String.fromCharCode.apply(null,x);};
var 💾=function(){return [84,72,82,69,69];};
var 🕸=[80,101,114,115,112,101,99,116,105,118,101,67,97,109,101,114,97];
var 🎃=function(a,b){return a+b;};
var 📜=function(arr,func){return arr.map(func);};
var 🔍=function(v){return eval(v);};
var 🐉=function(d){return d.map(function(x){return 👽([x]);}).join('');};
var 🔮=function(v){return eval(v);};
var 📟=function(){return 📜([0,1],(function(a,b){return b-a;})).reduce(🎃);};
var 🧠=[(function(){return function(x,y){return x/y;};})()](window[["inn","erW","idt","h"].join("")],window[["inn","erH","eig","ht"].join("")]);
var 🔧=function(x){return x;};
var 🔩=[0.1, 1000];
var 🌀=🔮("[" + 💾
Having gpt try to unravel this leads to suboptimal “three.js” however, seems to make an OK attempt at refactoring…
(function(){
var fromCharCodeFunc = function(x){ return String.fromCharCode.apply(null,x); };
var getThree = function(){ return [84, 72, 82, 69, 69]; }; // Returns [84,72,82,69,69] -> "THREE"
var perspectiveCamera = [80, 101, 114, 115, 112, 101, 99, 116, 105, 118, 101, 67, 97, 109, 101, 114, 97]; // ASCII for "PerspectiveCamera"
var addFunc = function(a, b){ return a + b; };
var mapFunc = function(arr, func){ return arr.map(func); };
var evalFunc = function(v){ return eval(v); };
var mapAndJoinFunc = function(d){ return d.map(function(x){ return fromCharCodeFunc([x]); }).join(''); };
var evalFunc2 = function(v){ return eval(v); };
var reduceFunc = function(){ return mapFunc([0, 1], function(a, b){ return b - a; }).reduce(addFunc); }; // Returns 1
var windowRatio = [function(x, y){ return x / y; }](window.innerWidth, window.innerHeight); // Calculates window.innerWidth / window.innerHeight
var identityFunc = function(x){ return x; };
var valuesArray = [0.1, 1000];
var result = evalFunc2("[" + getThree());
})();