最后更新于2023年4月25日星期二21:25:29 GMT

这篇文章是这个系列的第三篇, 圣诞节的12天, 让我们看看2014年Metasploit框架的一些更显著的进步和事件.

几个月前,魏 sinn3r Chen和我对Metasploit的Javascript混淆器jsobfu进行了一些改进. 最值得注意的是,我们把它搬到了自己的地方 repo and gem, 将其封装在测试中, 增强了抗病毒能力, 并添加了一个命令行接口,以便可以在metasploit-framework之外的CLI中使用它.

多年来的困惑

jsobfu是詹姆斯写的 egypt 它是框架中第一个使用正确解析器(tenderlove的)的Javascript混淆器 rkelly gem)和AST转换来混淆. 它是用来代替 雷克斯::剥削::ObfuscateJS mixin, 这是一个更简单,更低效的基于正则表达式的变量重命名器(它仍然在框架中支持遗留模块, 但jsobfu是当今的发展方向). 同样有用的还有 雷克斯::剥削::EncryptJS mixin from L4teral, 它用随机的异或键编码恶意Javascript并将其包装在eval包装器中. 这在处理静态/签名的浏览器AV引擎时非常方便.

Module Usage

如果您正在编写浏览器利用或Javascript开发后模块, 我们添加了一个方便的mixin,允许极其简单的混淆,最终用户可以通过一个数据存储选项来控制. 你的代码看起来像这样:

包括无国界医生组织:利用::JSObfu

def generate_html
  js_obfuscate(“trigger_exploit();”);
end

请注意 无国界医生组织:利用::JSObfu 的时候,Mixin会自动被拉进来 BrowserExploitServer.

When the js_obfuscate 方法使用, 用户可以通过调用的高级数据存储选项来控制混淆迭代的级别 JsObfuscate:

名称:JsObfuscate
电流设置:0
描述:混淆JavaScript的次数

The Gem

The new jsobfu红宝石宝石 Ruby gem可以快速安装:

安装jsobfu

这将安装 jsobfu 库并添加一个全局的 jsobfu shell命令,将从stdin中读取Javascript代码并对其进行混淆:

$ echo "console ".log('Hello World')" | jsobfu

window[(function () { var E="ole",d="ons",f="c"; return f+d+E })()][(String.fromChar
代码(108111、0147)))(字符串.x65 x48 fromCharCode(0, 0, 0154年,0154年,111年,32岁,0127年,0 x6f, 114年01
54,0x64));

还有一个选项 iterations 参数,允许您混淆指定次数:

$ echo "console ".log('Hello World')" | jsobfu 3

窗口((()函数{var T =字符串(字符串.0 x6f fromCharCode(102114年,109年,0 x43,104, 97 0 x
72、0 x43, 0157 0145 0 x64))((“j”.长度* 0 x39 + 54),(“h”.长度*(3 *(“X”.长度* 024 + 8)+ 9)+
15),(1*('Q'.*长度(1 * 0 x40 + 14) + 19 + 4)), Z =(()函数{var c =字符串.fromCharCode (0 x6e,
0163), I =字符串.fromCharCode (99 0 x6f),返回我+ c;})();返回Z + T;}) ()] [(String[(撑
g[((function () { var r="de",t="mCharCo",M="f",_="ro"; return M+_+t+r })())]((0x6*0x
f+12),(01*('J'.length*('z'.*长度(4 * 0 x9 + 4) + 27) + 1) + 46) (0 x37 *“Bw”.长度+ 1)(“K”.len
高等*段(0 x3 * 0 x1a + 17) + 14),(02 *(1 *(1 *(05年*“RIZ”.长度+ 2)+ 6)+ 3)+ 15),(“X”.*长度(' zzJA '.le
ngth * 021 + 15) + 21), (0 x1 * 0111 + 24)(“颗”.长度* 0 x2b + 28),(“z”.长度* 0 x43 + 0)、(03 * 33 + 12),
('AZa'.*长度(' NKY '.长度* (02 * 4 + 3)+ 0)+ 1),(1 * 0 x5c + 9))))((“u”.*长度(01 *(“KR”.lengt
h*('av'.长度* 0 x7 + 3 + 5) + 19) +(1 *(“j”.长度* 056 + 0)+ 4))(“z”.*(字符串长度.fromChar
Code(0x67,85,0155,0156,75,84,0114,0x4c)[((function () { var f="ngth",F="e",x="l"; re
turn x+F+f })())]*((function () { var n='m',a='Q'; return a+n })()[(String.fromCharC
ode(0154,101,110,0x67,0x74,104))]*(function () { var w='d',A='tMf'; return A+w })()[
((function () { var yG="ngth",q5="e",J="l"; return J+q5+yG })())]+'SX'.) +“crFi长度
Kaq'.长度)+(1 * 026 + 2))(“p”.*长度(06 * 15 + 10)+“南京大学”.长度))))((S () {var En =函数
特林((字符串.x6f x72 fromCharCode (0146 0, 0, 0 x6d, 0103年,104年,97年,0 x72, 67 0 x6f, 0144, 101))) (
(3 * 041 + 9),(“eHUOhZL”.*长度(0 x1 * (1 * 9 + 1 + 3) + 9)), Y =(函数(){var z = (() {
var Sf='r'; return Sf })(),Z=(function () { var N='o'; return N })(),C=String.fromCh
arCode (0 x57);返回C + Z + Z;}) () (((k =字符串函数(){var b =“e”,s =“od”,p =“fromCha”
,H="rC"; return p+H+s+b })())](('C'.length*('H'.length*('Ia'.长度* 0 xf + 3) + 12) + 27), (
'G'.*(01 *(西弗吉尼亚州的长度.长度* 25 + 10)+ 27)+ 14),(“问”.长度* 077 + 45)(二盘棋由于”服务器的“.长度* 30 + 18),
(1*('B'.*长度(0 x1 * 29 + 20) + 24) + 38), (0 x2 * 020 + 0));返回k + Y + En;}) ());

实现

jsobfu最初的方法很简单:混淆字符串, object, 并通过将它们转换为可执行语句的随机块来对字面量进行编号. 例如,语句:

"ABC";

可以以多种不同的方式进行转换(变量在转换期间被重命名):

String.fromCharCode(0101 0×,0 x43);

Or:

(function () { var t="C",_="B",h="A"; return h+_+t })(); 

Or even:

(函数(){var k =字符串.fromCharCode (0103), d =字符串.fromCharCode(0×),
  v=(function () { var I="A"; return I })();return v+d+k;})(); 

为了使它在逃避AV时有用, 我们希望确保原始代码中的每个可签名字符串(可能)都是随机的. 因为Javascript允许从字符串中查找属性, 可以将所有属性查找重写为小的, 随机选择的代码块. 这使得去混淆对人类来说相当乏味, 由于大量代码正在执行,并且没有直接放置钩子的地方(与基于求值的方法相反).

所以如果你混淆了执行查找的代码:

// input:
Var obj = {};
var x = obj.y; 

查找将被随机选择的字符串文字转换混淆:

//混淆输出:
var K = {};
var X = K[(字符串).fromCharCode (0 x79))); 

还必须处理全局查找:

// input:
var x =全局对象.y;

对象解析全局查找 window 全局的,所以它们也可以被混淆:

//混淆输出:
var G =窗口[字符串].fromCharCode(0开发,x47 0 x6c 0 x6f, 0142年,97年,0 x6c, 79年,98年,0 x6a,
101,99,0x74)][((function () { var i="y"; return i })())];