解码 Javascript 文件之 C# 正则替换
在Web前端逆向时,经常会遇到混肴加密的JS,比如下面的原始JSvar _0x1056b1=_0x195f;(function(_0x5d4e30,_0x48c9c6){var _0xc2c325=_0x195f,_0x50f292=_0x5d4e30();while(!![]){try{var _0x461dae=parseInt(_0xc2c325(0x1e7))/0x1+-parseInt(_0xc2c325(0x1d4))/0x2+-parseInt(_0xc2c325(0x1d6))/0x3+parseInt(_0xc2c325(0x1d7))/0x4+parseInt(_0xc2c325(0x1f3))/0x5*(parseInt(_0xc2c325(0x1f8))/0x6)+parseInt(_0xc2c325(0x1e8))/0x7+-parseInt(_0xc2c325(0x1df))/0x8;if(_0x461dae===_0x48c9c6)break;else _0x50f292['push'](_0x50f292['shift']());}catch(_0x436e53){_0x50f292['push'](_0x50f292['shift']());}}}(_0x4309,0x920ef),$(document)(function(){var _0x11c06f=_0x1056b1,_0x284d4d=window;$(_0x11c06f(0x1f7))['filter'](function(){var _0x214f26=_0x11c06f;return this==_0x284d4d;})(_0x11c06f(0x1f2)),$(_0x11c06f(0x1f7))(function(){var _0x1c5b20=_0x11c06f;return this+'#'==_0x284d4d;})['addClass']('active');}));function _0x195f(_0x2630a3,_0x13a8ed){var _0x430959=_0x4309();return _0x195f=function(_0x195fba,_0x490f64){_0x195fba=_0x195fba-0x1d4;var _0x56a5ba=_0x430959;return _0x56a5ba;},_0x195f(_0x2630a3,_0x13a8ed);}function switch_proj(_0x22df2b){var _0x52381c=_0x1056b1;$({'url':_0x52381c(0x1ed),'type':'POST','data':{'project_id':_0x22df2b['id']},'dataType':'json','success':function(_0x5f5891){var _0x5cbb93=_0x52381c;response=_0x5f5891,_0x5f5891=_0x5f5891;if(response=='success'){active_project=document(_0x5cbb93(0x1e5));var _0x5e20bf=document['getElementById'](_0x22df2b['id']);active_project=_0x5e20bf,active_project=document['getElementById']('current_active_project2'),active_project['innerText']=_0x5e20bf;}else alert(_0x5f5891);}});}function _0x4309(){var _0x5cbed7=['6101864rlJFPI','data','textContent','hide','ajax','getElementById','current_active_project','reload','453406xKGppO','2619750tfYSkd','href','#projectcreation_error','ready','#projecttext','/switch-project','project_name','innerText','response','POST','active','35IfdNdC','#projectcreation_success','projectcreation_success','create','ul.nav\x20a','435684KAJSHB','498572KPcLCy','location','1257909VYUmQG','2774492jOaOCZ','#createProjectSpinner','/project-handling','addClass','content','show','projectcreation_error','filter'];_0x4309=function(){return _0x5cbed7;};return _0x4309();}function create_project(){var _0x447cef=_0x1056b1;$(_0x447cef(0x1ec))(),$(_0x447cef(0x1d8))(),project_name=document(_0x447cef(0x1ee))['value'],$({'url':_0x447cef(0x1d9),'type':_0x447cef(0x1f1),'data':{'action':_0x447cef(0x1f6),'project_name':project_name},'success':function(_0x1fcfdb){var _0x3c6a45=_0x447cef;$(_0x3c6a45(0x1ec))(),$('#createProjectSpinner')['hide']();var _0x25fdf8=_0x1fcfdb,_0x190897=_0x1fcfdb;_0x25fdf8=='success'?($(_0x3c6a45(0x1f4))(),document(_0x3c6a45(0x1f5))['textContent']=_0x190897,location()):($(_0x3c6a45(0x1ea))(),document(_0x3c6a45(0x1dd))=_0x190897);}});}
上面的JS文件几乎无法阅读,这时候我们先要格式化它,比如拿到VSCode中使用格式化插件处理一下,然后再人工处理,把不容易理解的混肴变量重命名一下,之后可以得到如下的JS代码:
function __getArray() {
var array = [
"6101864rlJFPI",
"data",
"textContent",
"hide",
"ajax",
"getElementById",
"current_active_project",
"reload",
"453406xKGppO",
"2619750tfYSkd",
"href",
"#projectcreation_error",
"ready",
"#projecttext",
"/switch-project",
"project_name",
"innerText",
"response",
"POST",
"active",
"35IfdNdC",
"#projectcreation_success",
"projectcreation_success",
"create",
"ul.nav a",
"435684KAJSHB",
"498572KPcLCy",
"location",
"1257909VYUmQG",
"2774492jOaOCZ",
"#createProjectSpinner",
"/project-handling",
"addClass",
"content",
"show",
"projectcreation_error",
"filter",
];
return array;
}
function _getName(index) {
var array = __getArray();
var _index = _index - 0x1d4;
var name = array;
return name;
}
(function (_getArray, _break_val) {
var array = _getArray();
while (true) {
try {
var result =
parseInt(_getName(0x1e7)) / 0x1 +
-parseInt(_getName(0x1d4)) / 0x2 +
-parseInt(_getName(0x1d6)) / 0x3 +
parseInt(_getName(0x1d7)) / 0x4 +
(parseInt(_getName(0x1f3)) / 0x5) *
(parseInt(_getName(0x1f8)) / 0x6) +
parseInt(_getName(0x1e8)) / 0x7 +
-parseInt(_getName(0x1df)) / 0x8;
if (result === _break_val) break;
else array["push"](array["shift"]());
} catch (_0x436e53) {
array["push"](array["shift"]());
}
}
})(__getArray, __break_val);
$(document)(function () {
var value = window;
$(_getName(0x1f7))
["filter"](function () {
return this == value;
})
(_getName(0x1f2));
$(_getName(0x1f7))
(function () {
return this + "#" == value;
})
["addClass"]("active");
});
function switch_proj(model) {
$({
url: _getName(0x1ed),
type: "POST",
data: { project_id: model["id"] },
dataType: "json",
success: function (data) {
response = data;
data = data;
if (response == "success") {
active_project = document(_getName(0x1e5));
var attr = document["getElementById"](model["id"]);
active_project = attr;
active_project = document["getElementById"]("current_active_project2");
active_project["innerText"] = attr;
} else alert(data);
},
});
}
function create_project() {
$(_getName(0x1ec))();
$(_getName(0x1d8))();
project_name = document(_getName(0x1ee))["value"];
$({
url: _getName(0x1d9),
type: _getName(0x1f1),
data: { action: _getName(0x1f6), project_name: project_name },
success: function (data) {
$(_getName(0x1ec))();
$("#createProjectSpinner")["hide"]();
var value1 = data;
var value2 = data;
if (value1 == "success") {
$(_getName(0x1f4))();
document(_getName(0x1f5))["textContent"] = value2;
location();
} else {
$(_getName(0x1ea))();
document(_getName(0x1dd)) = value2;
}
},
});
}
我们可以看到,上面的代码已经很容易阅读了,但是还是有问题,很明显代码使用了一个数组,把部分参数混肴加密了,这时候我们需要替换掉这些地方 , 比如_getName(0x1e7)
由于本人比较收悉C#语言, 下面我使用C#编写的正则替换的代码, 把解码后的JS输出到一个新的文件
using System;
using System.Text.RegularExpressions;
var array = new string[]{
"6101864rlJFPI",
"data",
"textContent",
"hide",
"ajax",
"getElementById",
"current_active_project",
"reload",
"453406xKGppO",
"2619750tfYSkd",
"href",
"#projectcreation_error",
"ready",
"#projecttext",
"/switch-project",
"project_name",
"innerText",
"response",
"POST",
"active",
"35IfdNdC",
"#projectcreation_success",
"projectcreation_success",
"create",
"ul.nav 20a",
"435684KAJSHB",
"498572KPcLCy",
"location",
"1257909VYUmQG",
"2774492jOaOCZ",
"#createProjectSpinner",
"/project-handling",
"addClass",
"content",
"show",
"projectcreation_error",
"filter"
};
string? _getName(int index)
{
var _index = index - 0x1d4;
string? funcName = array;
return funcName;
}
var originJSFileName = "1.js";
var decodeJSFileName = "1.decode.js";
using FileStream fs = new(decodeJSFileName, FileMode.Create, FileAccess.Write);
using StreamWriter writer = new(fs);
//正则,用来匹配每行的 _getName(0x111)
var regex = new Regex("_getName\\((.+?)\\)");
//读取原始加密的js文件的所有行
var lines = File.ReadAllLines(originJSFileName);
//遍历处理每一行
foreach (var line in lines)
{
//处理每行匹配正则的所有字符串
var decodeLine = regex.Replace(line, new MatchEvaluator(match =>
{
var numberString = match.Groups.Value;
if (numberString == "index")
{
return match.Value;
}
//提取函数中的数字索引参数
int number;
if (numberString.StartsWith("0x"))
{
number = Convert.ToInt32(numberString, 16);
}
else
{
_ = int.TryParse(numberString, out number);
}
//获取实际的解密参数并返回
return $"\"{_getName(number)}\"";
}));
global::System.Console.WriteLine(decodeLine);
//写入解码后的每一行到新的文件中
writer.WriteLine(decodeLine);
}
Console.WriteLine("完成解码");
最终我得到的解码后的JS代码如下:
function __getArray() {
var array = [
"6101864rlJFPI",
"data",
"textContent",
"hide",
"ajax",
"getElementById",
"current_active_project",
"reload",
"453406xKGppO",
"2619750tfYSkd",
"href",
"#projectcreation_error",
"ready",
"#projecttext",
"/switch-project",
"project_name",
"innerText",
"response",
"POST",
"active",
"35IfdNdC",
"#projectcreation_success",
"projectcreation_success",
"create",
"ul.nav a",
"435684KAJSHB",
"498572KPcLCy",
"location",
"1257909VYUmQG",
"2774492jOaOCZ",
"#createProjectSpinner",
"/project-handling",
"addClass",
"content",
"show",
"projectcreation_error",
"filter",
];
return array;
}
function _getName(index) {
var array = __getArray();
var _index = _index - 0x1d4;
var name = array;
return name;
}
(function (_getArray, _break_val) {
var array = _getArray();
while (true) {
try {
var result =
parseInt("active") / 0x1 +
-parseInt("6101864rlJFPI") / 0x2 +
-parseInt("textContent") / 0x3 +
parseInt("hide") / 0x4 +
(parseInt("/project-handling") / 0x5) *
(parseInt("filter") / 0x6) +
parseInt("35IfdNdC") / 0x7 +
-parseInt("#projectcreation_error") / 0x8;
if (result === _break_val) break;
else array["push"](array["shift"]());
} catch (_0x436e53) {
array["push"](array["shift"]());
}
}
})(__getArray, __break_val);
$(document)["create"](function () {
var value = window["data"]["#projectcreation_success"];
$("projectcreation_error")
["filter"](function () {
return this["#projectcreation_success"] == value;
})
["current_active_project"]("#createProjectSpinner");
$("projectcreation_error")
["href"](function () {
return this["#projectcreation_success"] + "#" == value;
})
["addClass"]("active");
});
function switch_proj(model) {
$["project_name"]({
url: "435684KAJSHB",
type: "POST",
data: { project_id: model["id"] },
dataType: "json",
success: function (data) {
response = data["1257909VYUmQG"];
data = data["ready"];
if (response == "success") {
active_project = document["innerText"]("response");
var attr = document["getElementById"](model["id"])["location"];
active_project["location"] = attr;
active_project = document["getElementById"]("current_active_project2");
active_project["innerText"] = attr;
} else alert(data);
},
});
}
function create_project() {
$("ul.nav 20a")["/switch-project"]();
$("ajax")["453406xKGppO"]();
project_name = document["innerText"]("498572KPcLCy")["value"];
$["project_name"]({
url: "getElementById",
type: "2774492jOaOCZ",
data: { action: "show", project_name: project_name },
success: function (data) {
$("ul.nav 20a")["453406xKGppO"]();
$("#createProjectSpinner")["hide"]();
var value1 = data["1257909VYUmQG"];
var value2 = data["reload"];
if (value1 == "success") {
$("addClass")["453406xKGppO"]();
document["innerText"]("content")["textContent"] = value2;
location["POST"]();
} else {
$("projectcreation_success")["453406xKGppO"]();
document["innerText"]("2619750tfYSkd")["#projecttext"] = value2;
}
},
});
}
Broadm 发表于 2023-2-15 09:04
https://www.babeljs.cn/
Babel 是一个 JavaScript 编译器。
我没看到Babel能解决我所描述的问题, 请给 ...
这个是菜老板,用他的https://github.com/Tsaiboss/decodeObfuscator
可以直接还原cd decodeObfuscator
node main.js a.js b.js
然后出来的结果
$(document)["ready"](function () {
var _0x284d4d = window["location"]["href"];
$("ul.nav a")['filter'](function () {
return this["href"] == _0x284d4d;
})["addClass"]("active");
$("ul.nav a")["filter"](function () {
return this["href"] + '#' == _0x284d4d;
})['addClass']('active');
});
function switch_proj(_0x22df2b) {
$["ajax"]({
'url': "/switch-project",
'type': 'POST',
'data': {
'project_id': _0x22df2b['id']
},
'dataType': 'json',
'success': function (_0x5f5891) {
response = _0x5f5891["response"];
_0x5f5891 = _0x5f5891["data"];
if (response == 'success') {
active_project = document["getElementById"]("current_active_project");
var _0x5e20bf = document['getElementById'](_0x22df2b['id'])["innerText"];
active_project["innerText"] = _0x5e20bf;
active_project = document['getElementById']('current_active_project2');
active_project['innerText'] = _0x5e20bf;
} else {
alert(_0x5f5891);
}
}
});
}
function create_project() {
$("#projecttext")["hide"]();
$("#createProjectSpinner")["show"]();
project_name = document["getElementById"]("project_name")['value'];
$["ajax"]({
'url': "/project-handling",
'type': "POST",
'data': {
'action': "create",
'project_name': project_name
},
'success': function (_0x1fcfdb) {
$("#projecttext")["show"]();
$('#createProjectSpinner')['hide']();
var _0x25fdf8 = _0x1fcfdb["response"];
var _0x190897 = _0x1fcfdb["content"];
_0x25fdf8 == 'success' ? ($("#projectcreation_success")["show"](), document["getElementById"]("projectcreation_success")['textContent'] = _0x190897, location["reload"]()) : ($("#projectcreation_error")["show"](), document["getElementById"]("projectcreation_error")["textContent"] = _0x190897);
}
});
} 代码的思路没有问题, 其中有个循环修改数组的代码,被我遗漏了, 执行一下就能得到真实的数组了,然后就没有问题了
循环的代码如下
(function (_getArray, _break_value) {
var array = _getArray();
while (true) {
try {
var value =
parseInt(getName(0x1e7)) / 0x1 +
-parseInt(getName(0x1d4)) / 0x2 +
-parseInt(getName(0x1d6)) / 0x3 +
parseInt(getName(0x1d7)) / 0x4 +
(parseInt(getName(0x1f3)) / 0x5) * (parseInt(getName(0x1f8)) / 0x6) +
parseInt(getName(0x1e8)) / 0x7 +
-parseInt(getName(0x1df)) / 0x8;
if (value === _break_value) break;
else array["push"](array["shift"]());
} catch (_0x436e53) {
array["push"](array["shift"]());
}
}
})(getArray, 0x920ef);
执行一下这个代码就能得到真实的数组了, 然后最终的解码后的JS是
$(document)["ready"](function () {
var value = window["location"]["href"];
$("ul.nav a")
["filter"](function () {
return this["href"] == value;
})
["addClass"]("active");
$("ul.nav a")
["filter"](function () {
return this["href"] + "#" == value;
})
["addClass"]("active");
});
function switch_proj(model) {
$["ajax"]({
url: "/switch-project",
type: "POST",
data: { project_id: model["id"] },
dataType: "json",
success: function (data) {
response = data["response"];
data = data["data"];
if (response == "success") {
active_project = document["getElementById"]("current_active_project");
var attr = document["getElementById"](model["id"])["innerText"];
active_project["innerText"] = attr;
active_project = document["getElementById"]("current_active_project2");
active_project["innerText"] = attr;
} else alert(data);
},
});
}
function create_project() {
$("#projecttext")["hide"]();
$("#createProjectSpinner")["show"]();
project_name = document["getElementById"]("project_name")["value"];
$["ajax"]({
url: "/project-handling",
type: "POST",
data: { action: "create", project_name: project_name },
success: function (data) {
$("#projecttext")["show"]();
$("#createProjectSpinner")["hide"]();
var value1 = data["response"];
var value2 = data["content"];
if (value1 == "success") {
$("#projectcreation_success")["show"]();
document["getElementById"]("projectcreation_success")["textContent"] = value2;
location["reload"]();
} else {
$("#projectcreation_error")["show"]();
document["getElementById"]("projectcreation_error")["textContent"] = value2;
}
},
});
}
再次感谢大家的支持, 谢谢 :lol
最终的代码是这个:
$(document).ready(function () {
var _0x284d4d = window.location.href;
$("ul.nav a").filter(function () {
return this.href == _0x284d4d;
}).addClass("active");
$("ul.nav a").filter(function () {
return this.href + "#" == _0x284d4d;
}).addClass("active");
});
function switch_proj(_0x22df2b) {
$.ajax({
"url": "/switch-project",
"type": "POST",
"data": {
"project_id": _0x22df2b.id
},
"dataType": "json",
"success": function (_0x5f5891) {
response = _0x5f5891.response;
_0x5f5891 = _0x5f5891.data;
if (response == "success") {
active_project = document.getElementById("current_active_project");
var _0x5e20bf = document.getElementById(_0x22df2b.id).innerText;
active_project.innerText = _0x5e20bf;
active_project = document.getElementById("current_active_project2");
active_project.innerText = _0x5e20bf;
} else alert(_0x5f5891);
}
});
}
function create_project() {
$("#projecttext").hide();
$("#createProjectSpinner").show();
project_name = document.getElementById("project_name").value;
$.ajax({
"url": "/project-handling",
"type": "POST",
"data": {
"action": "create",
"project_name": project_name
},
"success": function (_0x1fcfdb) {
$("#projecttext").show();
$("#createProjectSpinner").hide();
var _0x25fdf8 = _0x1fcfdb.response;
var _0x190897 = _0x1fcfdb.content;
if (_0x25fdf8 == "success") {
$("#projectcreation_success").show();
document.getElementById("projectcreation_success").textContent = _0x190897;
location.reload();
} else {
$("#projectcreation_error").show();
document.getElementById("projectcreation_error").textContent = _0x190897;
}
}
});
} 平常看到浑浊的js代码就头晕,谢谢楼主分享 太复杂了,虽然看不懂,顶楼主一个! 厉害厉害支持楼主 楼主是大善人。 感谢楼主 刚好用上 了解一下babel库吧,js的代码,由js库来解决更好。 悦来客栈的老板 发表于 2023-2-15 08:47
了解一下babel库吧,js的代码,由js库来解决更好。
https://www.babeljs.cn/
Babel 是一个 JavaScript 编译器。
我没看到Babel能解决我所描述的问题, 请给出示范谢谢 夜泉 发表于 2023-2-14 22:05
最终的代码是这个:
$(document).ready(function () {
好的,学习了,我也是初学,主要是分享下解析过程,应该哪步出错了,可以帮助指出那个代码写错了吗?