Table of Contents
It’s been a while since I’ve posted about LandUpdate808. There was a compromised site that is local to Hawaii that I recently noticed, and it prompted me to research the current LandUpdate808 process.
Tactical Pause
THE CONTENT, VIEWS, AND OPINIONS EXPRESSED ON THIS DOCUMENT ARE MY OWN AND DO NOT REFLECT THOSE OF MY EMPLOYER OR ANY AFFILIATED ORGANIZATIONS. ALL RESEARCH, ANALYSIS, AND WRITING ARE CONDUCTED ON MY PERSONAL TIME AND USING MY OWN PERSONALLY-ACQUIRED RESOURCES. ANY REFERENCES, TOOLS, OR SOFTWARE MENTIONED HERE ARE LIKEWISE USED INDEPENDENTLY AND ARE NOT ASSOCIATED WITH, ENDORSED, OR FUNDED BY MY EMPLOYER.
LandUpdate808 Basics
LandUpdate808 is an exploit kit that is used to deliver malware. It injects a call to malicious code in compromised websites. When a visitor accesses a compromised website, they will load the attacker controlled resources that are used to trick the user into performing steps to download and execute malware. Previously, LandUpdate808 would trick victims into executing malware by disguising it as a required browser update. Currently, LandUpdate808 uses the ClickFix technique – that is, it present a dialog that tells the visitor they need to run a command that was copied to the visitor’s clipboard. When the visitor runs the command, it initiates a multi-stage download and execution process that leads to malware.
Note: LandUpdate808 is also tracked as Kongtuke.
If you’re interested, I show how I track LandUpdate808, TA582, and SmartApeSG infrastructure using DNS and IP info. Here’s the link: https://malasada.tech/silent-push-to-find-smartapesg-landupdate808-and-ta582-infra/
The Flow
Proofpoint released the latest post about the ET rule updates (https://x.com/ET_Labs/status/1875308766058704975). The most recent LandUpdate808 domain they’ve posted is usbkits[.]com. I did a quick glance in urlscan to see if there were any notable domains that were reaching out to usbkits[.]com – there was, and it’s a Hawaii-based website.
Analysis Displaying the ClickFix Message
The display stages begin with the normal LandUpdate808 steps, with the exception that it is now obfuscated. The first step downloads hxxps[:]//usbkits[.]com/0o9o.js. We can de-obfuscate it with deobfuscate.io.
In the snip below, lines 1-26 are the cookie functions. LandUpdate808 uses the cookie functions to ensure the visitor is not served the malicious prompt for 4 days.
The function getCookie on line 10 will be called to check if the cookie is present (ie. the user was served the malicious prompt within the last 4 days). If it is not present, the setCookie function on line 1 will be called, and it will set the cookie to expire in 4 days (the current time + the 3rd argument passed with the function called multiplied by 24, 60, 60, and 1000). The eraseCookie function is not observed being used.
The snip below shows the next parts.
Lines 27 checks that the “isCompleted” cookie does not exist before it executes the main parts. The “isCompleted” cookie is created on line 28, and it is passed the value of 4 for the 3rd argument. The HttpClient function is created on lines 29-40. On line 30, it starts configured the “get” function that will take 2 arguments.On line 34, if the GET request was successful, it will execute the function that was passed as the second argument – it will execute the responseText from the GET request.
Lines 41-47 gets the visitor’s public IP via a call to the Cloudflare “trace” endpoint.
The function to get the visitor’s browser begins on line 48. The function can be viewed better in the snip below.
Lines 48-74 are used to get the browser.
In the snip below, lines 75-99 are used to get the OS.
In the snip below, the rest of the script is executed via lines 100-120. On line 104, the GET URL string is created. It will send GET request to “hxxps[:]//usbkits[.]com/js.php”. The URL will contain parameters to pass info on the visitor such as their device, IP, the compromised site as the refferer, the browser, the user agent, the start of the next step URL, and the loc value that was returned from the Cloudflare trace endpoint.
On lines 109-111, if the response is less than 35 characters, it will output a fake “Jquery.js is loaded” message to console. If the response was greater than 35 characters, it will add the responseText to the DOM via line 113.
The response from the js.php endpoint is an HTML file. We can see the head in the snip below.
Line 7 sets the ipGlobal variable to my public IP that I’ve replaced with Xs. The xhrURIGlobal variable is set on line 8 to the stat.php endpoint on usbkits[.]com. Line 9 sets the commandGlobal variable to the PowerShell command that will be copied to the user’s browser.
Note: The .top domain on line 9 matches the behavior of what’s tracked as TA582. The “s” parameter of 527 appears to be unique to LandUpdate808. There are other “s” parameters that appears to be for other campaigns such as “mints13” or “mints21”.
The rest of the snips below for this step has been modified for viewability.
The snip below shows lines 20-27 configures the decryptcode function that will decrypt the encoded value that is passed as an argument, and it will remove the first 128 characters.
Lines 29-35 configure the applyMap function that is used to replace the obfuscated code with the original.
The decryptcode function will be used to decode the CSS, HTML, and then the JS. The CSS is first added to the document head, then the document inner HTML is replaced with the decoded HTML, and finally the decoded JS is appended to the document body.
The CSS doesn’t appear to have anything notable to mention.
The snip shows the B64 decoded text that was decoded in CyberChef. It was cleaned up to make it easier to view. Lines 20-39 configures the event listener for the verify button. The key takeaways is that it will send a POST to the stat.php endpoint on usbkits[.]com. The post will contain “X-ACCESS-11” as the key, and it will include the visitors public IP, and it will set “loaded” to “yes”. Additionally, it will set the user’s clipboard to “Captcha ID: 1ef45r”.
The snip below shows that on line 111 it is using the deprecated function execCommand. That is probably not very important, just highlighting it because I was recently asked how it copies to the clipboard. Other ClickFix implementations use the navigator.clipboard.writeText function.
After all that analysis, here are the snips showing what the user is presented. The first snip below shows the fake captcha.
The next snip below shows the instruction dialog that prompts the visitor to run the command that was copied to their clipboard.
Analyzing the PS portion
Going back to the snip that was re-pasted below, we can see line 9 contains the command that is copied to the clipboard.
We can modify this to the command below so that it isn’t in a separate hidden PS window. Also, we can remove the iex (short for the PowerShell Invoke-Expression cmdlet) so that it doesn’t execute.
After the command above is executed, we can save the content to a text file using the comand $global:block.content > 2.txt.
2.txt is obfuscated PowerShell code as seen below.
We can expect the code to perform string building and basic enumeration before downloading or executing the next step.
At the end we can see that the last step is to pipe to iex (the PowerShell Invoke-Expression cmdlet).
Because I suspected the staging servers may how long it takes between steps, I simply replaced iex with echo >> 3.txt.
With the snip below, we can see that it performs obfuscated functions before curling a URL and executing it.
Again, for the sake of timeliness, I replaced the iex with the echo command, and sent the output to 4.txt. The value of 4.txt can be observed below.
We can see that it performs some obfuscated functions, and then it downloads an executable, saves it as “aa.exe”, and then executes it via the start-process cmdlet. This can be neutered by running everything except line 5.
During analysis, the first attempt was a goof up on my part. I downloaded the executable (I thought I did) via the command on line 4. It was actually an HTML block page notifying me that Spectrum Security Shield blocked the download.
On the next attempt, the download attempt returns the error “Maximum download limit reached” – as seen in the snip below.
I’m unable to download that executable, so the buck stops here. Before we conclude, we can discuss the 2nd look at the PowerShell steps that I skipped through.
2nd Look – PS Step 2
This is the step that is after the step where the user is tricked into executing the Step 1 PowerShell from the ClickFix. I ran a very basic script that performs the math functions and computes most of the string values. Next, I updated some variable names to names that make sense. For the most part, Step 2 is used to load Step 3 into memory and execute it. In the snip below, line 1 gets the execution context, but it’s not used, and lines 2-5 perform an unknown function.
In the snip below, Lines 7-33 are used to decode the parameter from Base 64, bitwise XOR it, decompress it (GZIP), and then return the value to the caller.
The snip below shows the decoder function is called on line 34 with the B64 value as the parameter.
At the bottom of that, the string value is piped to iex for execution.
2nd Look – PS Step 3
For this step, I performed the same process of running a basic script that I wrote to compute the math functions, and calculate the strings. There are some parts where the script had minor logic errors, such as not removing the parenthesis around a string that was computed, but for the most part – it’s good enough to understand what’s going on. Additionally, I renamed the variable names to names that were better fit. The snip below shows the decoded Step 3.
On line 1, the variable is set for the execution context. Line 2 checks if the system is a virtual machine, and lines 3-7 are used to increment “sumForKey” based on the value.
Similar steps are performed based on the video controller adapter type response (on lines 8-13), and also for the cache memory purpose value (lines 16-21).
I’m unable to determine how the domain and PHP strings are calculated, but they are calculated in lines 23-33.
The final steps are on lines 34 and 35 where the next step is downloaded via a curl command, and it is executed via a pipe to iex.
2nd Look – PS Step 4
I performed the same steps to de-obfuscate step for and to make it easier to understand. The snip below shows the final result.
On line 3, the variable is configured to build the string containing System Management Automation AmsiUtils. It does this by using a string with non-standard letters, and then normalizing it to the regular characters.
After a brief sleep for 833 on line 5, the script will attempt to set the value of amsiinitfailed to true to attempt to shut off AMSI protection.
Finally, the script will download the next stage executable and save it as “aa.exe” in the temp folder, as seen on line 8, before executing it on line 9.
Summary
This documents the analysis steps for the LandUpdate808 exploit kit. The operators add code to compromised sites to load their malicious JavaScript file. This leads to the ClickFix technique where the visitor is instructed to run code, that was copied from the website to their clipboard, on their computer to verify they’re not a robot. The code is a PowerShell command to download the next PS step from a TA582 domain. There’s a few more steps before the final payload is downloaded and executed. Before that occurs, the PS code enumerates system values to determine if the host is a virtual machine and disables AMSI protection. In my analysis, I was unable to download the final payload because it returned the error stating the max downloads were reached.
IOCs
usbkits[.]com
nfuvueibzi4[.]top
kcehmenjdibnmi[.]top
hxxps[:]//usbkits[.]com/0o9o.js
hxxps[:]//usbkits[.]com/js.php?
hxxp[:]//nfuvueibzi4[.]top/1.php?s=527
hxxp[:]//kcehmenjdibnmi[.]top/m8t6y7egj2htr.php?
hxxp[:]//temp[.]sh/utDKu/138d2a62b73e89fc4d09416bcefed27e139ae90016ba4493efc5fbf43b66acfa.exe
138d2a62b73e89fc4d09416bcefed27e139ae90016ba4493efc5fbf43b66acfa.exe