REVIEWED by Sophos
See the story from Sophos Labs Uncut on KingMiner: https://news.sophos.com/en-us/2020/06/09/kingminer-report/
The article is both educational and enlightening. One of the aspects of KingMiner that is common with other attacks is that many of the indicators of compromise are non-deterministic. The domain names and URLs they use are all auto generated. I read through the article and crafted a query to check if you have experianced a Kingminer attack but because the indicators are not sufficient to convict with 100% accuracy I suspect we will have some false positive detections. Even with the FP rate above 0 each of the detections warrents a deeper investigation. See below for the query.
-------------------------------------- QUERY TEXT BELOW --------------------------------------------
/************************************************************\| IOC Partial list for Kingminer from Sophos Naked Security Article |\************************************************************/
/* Build the list of IOCs from the article */WITH kingminer_IOCs(attribution, Conviction, method, ioc, notes) AS ( VALUES /*****************************************************************************************\ | These servers used domain names that were generated from the value of the current date | | and time. This method has the advantage that the downloaders don’t have to carry | | hardcoded server names, rather those server names are dynamically generated and keep | | changing with time. This way, if one of the download servers is shut down, the operators| | don’t have to release new versions of the downloader with the updated server names. | | Instead, they just register the next domain name, and when the time comes, the botnet | | will automatically switch to the new download servers. | | The generated domain names have the following structure: 3615.30713fdae.tk | | The fdae.tk part is the core of the domain name. In the observed cases it was either | | fdae.tk, fdae.com or fghh.com, but the strings found in the side-loading DLLs suggest | | that additionally the fdae.ga and fdae.cf domain cores could potentially be used, or | | were planned to be used at some point | \*****************************************************************************************/ ('kingminer', 'NON-deterministic', 'domain_name', '%fdae.tk', 'Time-coded DGA - These servers used domain names that were generated from the value of the current date and time.'), ('kingminer', 'NON-deterministic', 'domain_name', '%fdae.com', 'Time-coded DGA - These servers used domain names that were generated from the value of the current date and time.'), ('kingminer', 'NON-deterministic', 'domain_name', '%fghh.com', 'Time-coded DGA - These servers used domain names that were generated from the value of the current date and time.'), ('kingminer', 'NON-deterministic', 'domain_name', '%fgae.ga', 'Time-coded DGA - These servers used domain names that were generated from the value of the current date and time.'), ('kingminer', 'NON-deterministic', 'domain_name', '%fghh.cf', 'Time-coded DGA - These servers used domain names that were generated from the value of the current date and time.'), ('kingminer', 'NON-deterministic', 'domain_name', '%a.qwerr.ga', 'Time-coded DGA - These servers used domain names that were generated from the value of the current date and time.'), ('kingminer', 'NON-deterministic', 'domain_name', '%lu4n.com', 'The lu4n.com site also hosted a few SQL brute forcing command injection tools'), ('kingminer', 'Deterministic', 'domain_name', '%ip.yototoo.com', 'encrypted backdoor connection'), /******************************************************************************************\ | We have found over 20 Github user accounts that were used to deliver the contents of the | | Kingminer botnet over the time. | \******************************************************************************************/ ('kingminer', 'NON-deterministic', 'URL', '%github%cvffdscccss%', 'Github repositories used to deliver contents of kingminer botnet'), ('kingminer', 'NON-deterministic', 'URL', '%github%xieliang3%', 'Github repositories used to deliver contents of kingminer botnet'), ('kingminer', 'NON-deterministic', 'URL', '%github%hansho23%', 'Github repositories used to deliver contents of kingminer botnet'), ('kingminer', 'NON-deterministic', 'URL', '%github%paishi45276%', 'Github repositories used to deliver contents of kingminer botnet'), ('kingminer', 'NON-deterministic', 'URL', '%github%oit847996%', 'Github repositories used to deliver contents of kingminer botnet'), ('kingminer', 'NON-deterministic', 'URL', '%github%muzhuoyiyue%', 'Github repositories used to deliver contents of kingminer botnet'), ('kingminer', 'NON-deterministic', 'URL', '%github%daonaoyef%', 'Github repositories used to deliver contents of kingminer botnet'), ('kingminer', 'NON-deterministic', 'URL', '%github%leishi9%', 'Github repositories used to deliver contents of kingminer botnet'), ('kingminer', 'NON-deterministic', 'URL', '%github%yut42929%', 'Github repositories used to deliver contents of kingminer botnet'), ('kingminer', 'NON-deterministic', 'URL', '%github%shazhuangq%', 'Github repositories used to deliver contents of kingminer botnet'), ('kingminer', 'NON-deterministic', 'URL', '%github%zaiya00387%', 'Github repositories used to deliver contents of kingminer botnet'), ('kingminer', 'NON-deterministic', 'URL', '%github%gghhjjjj%', 'Github repositories used to deliver contents of kingminer botnet'), ('kingminer', 'NON-deterministic', 'URL', '%github%gghhhhgh%', 'Github repositories used to deliver contents of kingminer botnet'), ('kingminer', 'NON-deterministic', 'URL', '%github%haj08341%', 'Github repositories used to deliver contents of kingminer botnet'), ('kingminer', 'NON-deterministic', 'URL', '%github%qipu872262484%', 'Github repositories used to deliver contents of kingminer botnet'), ('kingminer', 'NON-deterministic', 'URL', '%github%jiaoyi7992%', 'Github repositories used to deliver contents of kingminer botnet'), ('kingminer', 'NON-deterministic', 'URL', '%github%huitun237%', 'Github repositories used to deliver contents of kingminer botnet'), ('kingminer', 'NON-deterministic', 'URL', '%github%zaiya00387%', 'Github repositories used to deliver contents of kingminer botnet'), ('kingminer', 'NON-deterministic', 'URL', '%github%fff%', 'Github repositories used to deliver contents of kingminer botnet'), ('kingminer', 'NON-deterministic', 'URL', '%github%chigutuiche%', 'Github repositories used to deliver contents of kingminer botnet'), ('kingminer', 'NON-deterministic', 'URL', '%github%zhizi471%', 'Github repositories used to deliver contents of kingminer botnet'), ('kingminer', 'NON-deterministic', 'URL', '%github%jiaoshq %', 'Github repositories used to deliver contents of kingminer botnet'), /*****************************************************************************************\ | Usually the first activity that we observed after a successful infection was the | | execution of a PowerShell script spawned from the sqlservr.exe process | | !!! TO_DO !!! Build detection method for this type of IOC | \*****************************************************************************************/ /* ('kingminer', 'NON-deterministic', 'Powershell_Parent', '%sqlserver.exe%', 'successful infection was the execution of a PowerShell script spawned from the sqlservr.exe process'), */ /*****************************************************************************************\ | Copy of powershell.exe running under anothername | \*****************************************************************************************/ ('kingminer', 'NON-deterministic', 'Powershell_renamed', '%powershell%', 'A powershell process runing under another name'), /*****************************************************************************************\ | In one of the cases, we were able to observe the network traffic of an initial infection| | attempt, which helped us reconstruct the majority of the infection process. The attack | | in that case came from the IP address 185.234.216.223. | \*****************************************************************************************/ ('kingminer', 'Non-Deterministic', 'IP', '185.234.216.223', 'this server is part of the Kingminer infrastructure'), ('kingminer', 'Non-Deterministic', 'IP', '9.9.9.9', 'The malicious loader contains the IP addresses of a few DNS servers'), ('kingminer', 'Non-Deterministic', 'IP', '1.1.1.1', 'The malicious loader contains the IP addresses of a few DNS servers'), ('kingminer', 'Non-Deterministic', 'IP', '119.29.29.29', 'The malicious loader contains the IP addresses of a few DNS servers'), ('kingminer', 'Non-Deterministic', 'IP', '8.8.4.4', 'The malicious loader contains the IP addresses of a few DNS servers'), /*****************************************************************************************\ | this script is saved to a couple of locations, typically C:\Users\Public\Music\1.vbs. | \*****************************************************************************************/ ('kingminer', 'Non-Deterministic', 'file_path', 'C:\Users\Public\Music\1.vbs', 'VBscript downloader'), ('kingminer', 'Non-Deterministic', 'file_path', 'C:\Users\Public\Music\2.vbs', 'VBscript downloader'),
/*****************************************************************************************\ | some cmd line options used | \*****************************************************************************************/ ('kingminer', 'Non-Deterministic', 'cmdline', '%whoami%', 'luan_exec reference'), ('kingminer', 'Non-Deterministic', 'cmdline', '%vbscript:GetObject(%script:ww.3113cfdae.com/r1.txt', 'Kingminer executes this simple downloader command'),
/*****************************************************************************************\ | There were a handful of legit programs that were abused by Kingminer, coming from | | different software vendors | \*****************************************************************************************/ ('kingminer', 'Non-Deterministic', 'processname', 'fix.exe', 'Clean executable may be used to trigger malware via side loading'), ('kingminer', 'Non-Deterministic', 'processname', 'alger.exe', 'Clean executable may be used to trigger malware via side loading'), ('kingminer', 'Non-Deterministic', 'processname', 'powered.exe', 'Clean executable may be used to trigger malware via side loading'), ('kingminer', 'Non-Deterministic', 'processname', 'repair.exe', 'Clean executable may be used to trigger malware via side loading'), ('kingminer', 'Non-Deterministic', 'processname', 'dwmer.exe', 'Clean executable may be used to trigger malware via side loading'))/**********************************************************************\| The admin may want to search a large amount of data in the tables so || split time into 20 min chunks given the number hours specified |\**********************************************************************/, for(x) AS ( VALUES ( ( SELECT CAST (strftime ('%s', 'now','-$$Hours to look back$$ hours') AS INT) ) ) UNION ALL SELECT x+1200 FROM for WHERE x < (SELECT CAST (strftime ('%s', 'now') AS INT)))
/****************************************************************************\| Check for matching domain or URL info seen in the specified lookback period|\****************************************************************************/SELECT CAST( datetime(spa.time,'unixepoch') AS TEXT) DATE_TIME, km.attribution, km.Conviction, spa.subject, spa.SophosPID, CAST ( (select replace(spa.pathname, rtrim(spa.pathname, replace(spa.pathname, '\', '')), '')) AS TEXT) process_name, spa.action, spa.object, spa.url, km.method, km.ioc, km.notesFROM for LEFT JOIN kingminer_IOCs km ON km.method IN('domain_name', 'url') LEFT JOIN sophos_process_activity spa ON spa.subject IN ('Http','Url','Network') AND spa.time >= for.x and spa.time <= for.x+1200WHERE spa.url LIKE km.ioc
UNION ALL
/****************************************************************************\| Check for matching IP info seen in the specified lookback period |\****************************************************************************/SELECT CAST( datetime(spa.time,'unixepoch') AS TEXT) DATE_TIME, km.attribution, km.Conviction, spa.subject, spa.SophosPID, CAST ( (select replace(spa.pathname, rtrim(spa.pathname, replace(spa.pathname, '\', '')), '')) AS TEXT) process_name, spa.action, spa.object, spa.url, km.method, km.ioc, km.notesFROM for LEFT JOIN kingminer_IOCs km ON km.method IN('ip') LEFT JOIN sophos_process_activity spa ON spa.subject IN ('Http','Ip','Network') AND spa.time >= for.x and spa.time <= for.x+1200WHERE spa.source LIKE km.ioc OR spa.destination LIKE km.ioc
/***********************************************************************************\| Check for matching cmdline or file_path info seen in the specified lookback period|\***********************************************************************************/SELECT CAST( datetime(spa.time,'unixepoch') AS TEXT) DATE_TIME, km.attribution, km.Conviction, spa.subject, spa.SophosPID, CAST ( (select replace(spa.pathname, rtrim(spa.pathname, replace(spa.pathname, '\', '')), '')) AS TEXT) process_name, spa.action, spa.object, spa.url, km.method, km.ioc, km.notesFROM for LEFT JOIN kingminer_IOCs km ON km.method IN('cmdline','file_path') LEFT JOIN sophos_process_activity spa ON spa.subject IN ('FileBinaryChanges','FileBinaryReads','FileDataChanges','FileDataReads','FileOtherChanges','FileOtherReads', 'Image','Process') ANDspa.time >= for.x and spa.time <= for.x+1200WHERE spa.pathname LIKE km.ioc OR spa.cmdline LIKE km.ioc
/***********************************************************************************\| Check for powershell rename events |\***********************************************************************************/SELECT CAST( datetime(spa.time,'unixepoch') AS TEXT) DATE_TIME, km.attribution, km.Conviction, spa.subject, spa.SophosPID, CAST ( (select replace(spa.pathname, rtrim(spa.pathname, replace(spa.pathname, '\', '')), '')) AS TEXT) process_name, 'Powershell renamed', spa.object, spa.url, km.method, km.ioc, km.notesFROM for LEFT JOIN kingminer_IOCs km ON km.method IN('Powershell_renamed') LEFT JOIN sophos_process_activity spa ON spa.subject IN ('FileBinaryChanges','FileOtherChanges') ANDspa.time >= for.x and spa.time <= for.x+1200WHERE spa.pathname LIKE km.ioc
--------------------------------------- END SQL SCRIPT -------------------------------------