Skip to content

Instantly share code, notes, and snippets.

@da411d
Created August 12, 2019 17:40
Show Gist options
  • Save da411d/6e4472c0fe29908f52f232f668b823c5 to your computer and use it in GitHub Desktop.
Save da411d/6e4472c0fe29908f52f232f668b823c5 to your computer and use it in GitHub Desktop.
Скрипт для деобфускації js-файлів, обфускованих через obfuscator.io
const fs = require('fs').promises;
const beautify = require('js-beautify').js;
const path = require('path');
const _done_prefix = "/*DAKI:DONE*/";
async function walk(dir, fileList = []) {
const files = await fs.readdir(dir)
for (const file of files) {
const stat = await fs.stat(path.join(dir, file))
if (stat.isDirectory()) fileList = await walk(path.join(dir, file), fileList)
else fileList.push(path.join(dir, file))
}
return fileList
};
function addSlashes(s){
return s
.replace(/'/g, "\\'")
.replace(/\\u/g, "\\\\u")
.replace(/\\x/g, "\\\\x")
.replace(/\\s/g, "\\\\s")
.replace(/\\S/g, "\\\\S")
.replace(/\\w/g, "\\\\w")
.replace(/\\W/g, "\\\\W")
.replace(/\r/g, "\\r")
.replace(/\n/g, "\\n");
}
(async () => {
let list = await walk('./js.original/');
for(let file of list){
console.log();
console.log(file);
let content = (await fs.readFile(file)).toString();
if(content.includes(_done_prefix)){
console.log("File was already decoded");
continue;
}
// Content decode
content = content.replace(/\'(\\(x|u)[0-9a-f]{1,6})+\'/ig, (s) => {
let result = addSlashes(eval(s));
return "'" + result + "'";
});
// Replace keywords
var matchContent = content.match(/var _0x([0-9a-f]+)=(\[.+\]);\(function\((.*)/);
var keywordsArray = matchContent[2];
keywordsArray = eval(keywordsArray);
rotateIterationsCount = matchContent[3].match(/\(_0x[0-9a-f]{2,8},0x([0-9a-f]{2,8})\)/i)[1];
rotateIterationsCount = parseInt(rotateIterationsCount, 16);
for(var i=0; i<rotateIterationsCount; i++) {
keywordsArray.push(keywordsArray.shift());
}
let restOfCode = content.split(/\(\);\}\(_0x[0-9a-f]{2,8},0x[0-9a-f]{2,8}\)\);/i)[1];
let getKeywordFunctionName = restOfCode.match(/var (_0x[0-9a-f]+)=function\(_0x[0-9a-f]{2,8},_0x[0-9a-f]{2,8}\){/)[1];
// Replace keywords
let extractKeywoardGetterRegExp = new RegExp(getKeywordFunctionName+"\\('(0x[0-9a-z]+)'\\)", "ig");
restOfCode = restOfCode
.replace(extractKeywoardGetterRegExp, (s, index) => {
index = parseInt(index);
let result = addSlashes(keywordsArray[index]);
return "'" + result + "'";
});
// Replace object keys
restOfCode = restOfCode.replace(/instanceof/ig, " instanceof");
for(let i=0; i<10; i++){
restOfCode = restOfCode
.replace(/[^=:]\['(\w+)']/ig, (full, match) => full.substr(0, 1) + "." + match);
}
// Remove self-defender
// We just disable trigger
restOfCode = restOfCode.replace(/var (_0x[0-9a-f]{4,8})=function\(\){([0-9a-z_\s!(),.:;=?\[\]{}]{237})}\(\);/gi, 'var $1=function(){"THAT WAS A SELF-DEFENDING FUNCTION";return function(){}};');
restOfCode = beautify(restOfCode, {
indent_with_tabs: true,
end_with_newline: true,
break_chained_methods: true,
e4x: true
});
fs.writeFile(file.replace(".original", ""), _done_prefix+restOfCode);
console.log("File decoded successfully");
}
})();
@sugappa
Copy link

sugappa commented Dec 31, 2020

not work for me TypeError: Cannot read property '1' of null

@da411d
Copy link
Author

da411d commented Dec 31, 2020

@sugappa, this snippet was written long time ago, for one script obfuscated with concrete configuration.
Obfuscator was growing, protection was improved.

It will no longer work.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment