Skip to main content

Fake PDF converter leading to malicious Electron application through a WebView2 ⤜(ⱺ ʖ̯ⱺ)⤏

In October 2023 neonprimetime user reported on X (I hate this name) a possible new Redline stealer variant masquerading as a PDF converter named PdfConverters.exe (74b6039660be3eda726a4eee209679ba). This sample presents pretty interesting and unusual installation routine so I decided to take a closer look at it.

WebView2 application dropper

WebView2 allows you to embed web technologies (HTML, CSS, and JavaScript) in your native apps. It has been already proved this vector could be used in malicious purposes, however it is not popular among attackers.

The sample is dropping such application in %TEMP%\.net\PdfConverters directory. It also creates another folder in %TEMP%\PdfConverters.WebView2 which is used as a user data directory by the app. Then it loads the application through msedgewebview2.exe 

PdfConverters process tree

As already described by Noch Lab on his blog post, the main code of the application is written in C# and resides in app.dll (2e92db69ebdab1e5250985fc08ca87df) file. However, in my case dnSpy properly parsed the methods from the sample. Once executed, it initializes the WebView2 window with Visible flag set to false to avoid displaying anything to the user. Then it adds api class to the script running in the WebView2 and navigates to hXXps://www.pdfconvertercompare[.]com/main.

InitializeAsync() function

The URL was responding (it's not at the time of writing this article) with a HTML code with embedded <script src = "/main.js"></script> tag which was leading to downloading and executing JavaScript code by the WebView2 application.

main.js content

The neonprimetime's tweet (should I still call it a tweet or maybe xeet?) and blog post by Security Magic mentioned it leads to downloading PDFunk-Setup.exe binary but, in my case, the sample just sent 5 POST requests with some base64 encoded and encrypted data to the pdfconvertercompare[.]com domain and terminated itself. 

Closer look at the main.js

As you can see on the previous screenshot, the script is highly obfuscated. My first choice for deobfuscation is synchrony. It didn't disappoint me again and produced readable 5406 lines of spaghetti monster code. Key takeaways from the code:
  • It has 7 hardcoded domains which can be used for the C2 communication
    • pdfconvertercompare[.]com
    • createmygif[.]com
    • screen-records[.]com
    • videownload[.]com
    • pdfconverterz[.]com
    • zipextractors[.]com
    • econenectedithc[.]net
  • It generates .NET code which can be executed by this JS script through the api class of the app.dll.
  • ~3500 lines of the script are just implementation of multiple cryptography related algorithms (AES, SHA-256, SHA-224, SHA-512, SHA-384, RIPEMD160, MD5, SHA1, DES, 3DES, RC4, RC4Drop, Rabbit, RabbitLegacy, all padding schemes and modes for block ciphers)
  • It defines 7 functions which are responsible for posting some data in JSON format to one of the C2 domains.
    A function responsible for sending "log" type message

.NET code analysis

Main capabilities:
  • It is checking if any of the processes listed below are running on the system. If yes, it terminates the whole infection chain.
Blacklisted processes
  • Reading, writing and copying files.
    Write file function

  • Executing processes.
    Start a process function

  • Setting mouse and keyboard event hooks
    Set Windows Hooks function

  • Sending key strokes and clipboard manipulation
    Clipboard manipulation

  • Modification of Edge and Chrome Preferences and Secure Preferences entries.
    Edge Preferences modification.

All of the functions are being invoked by the JavaScript in some specific order which is quite easy to follow thanks to the log messages the script is supposed to send to the C2 server.

Example log messages

Payload encryption routine

As I mentioned before, I was able to observe just 5 POST requests to the C2 domain and then the sample terminated itself. The only option to push the analysis further was to decrypt the data sent to the C2. 

After putting together all the pieces it turned out the whole routine is quite simple:
  • Take the JSON as a string and encrypt it with RC4 algorithm with a hardcoded key.
  • Generate 20-30 random bytes and use them to XOR the RC4 encrypted data.
  • Add length of the key and the XOR key to the XORed data.
  • Base64 encode the data and send.
Payload decryption

With that, I was able to write a python script to simulate behaviour of the sample and see if I can get some additional stuff from the C2 server. After a little bit of playing the server finally replied to me with some Base64 data!

Response from the server

After decrypting I got something looking like a config.

searchers-three[.]com domain was not previously reported

Unfortunately at this point I still didn't have the PDFunk-Setup.exe file. Looking at the JavaScript, there is one particular request type which is responsible for getting this file, so I started playing with it as well.

fe (fetch?) request type

JSON fields description:
  • wv - always true.
  • t - type of request. To get the file it must be fe.
  • jv - constant 4.5.
  • iv - constant 1.0.
  • sid - session id. Random 18 digits.
  • rid - request id. Random 18 digits.
  • is - value taken from the config received previously.
  • did - value taken from the config received previously.
  • ts - timestamp.
  • d - debug flag? - false.
After sending a packet with the above payload to pdfconvertercompare[.]com I got the PDFunk-Setup.exe

PDFunk analysis

During the installation the file copies itself to %LocalAppData%\pdfunk-updater\installer.exe and drops the files to %LocalAppData%\Programs\PDFunk\. It also sets up a persistence by adding LNK file to the Startup folder pointing to %LocalAppData%\Programs\PDFunk\PDFunk.exe.

Finally the installer launches the main PDFunk.exe app which then spawns couple of child processes.

PDFunk process tree

Some of them are executed with --app-path parameter pointing to %LocalAppData%\Programs\PDFunk\resources\app.asar file. 

ASAR files are just Electron applications bundled into an archive format. The full application structure can be retrieved using npx (npx asar extract app.asar <destfolder>).

Our app looks like a fork of Electron PDF Viewer with additional obfuscated (of course) code inside main.js and index.js. Deobfuscating it reveals that the code is responsible for loading V8 bytecode as a cachedData into a Script object.

V8 bytecode execution

The bytecode is stored as a Base64 encoded string encrypted with RC4. Unfortunately I don't know how to statically analyze such bytecode so behavioral analysis is the only thing I could do at this point.

Every time the app is launched it sends a POST request to one of the domains:
  • haitingshospical[.]com
  • weiledstever[.]com
  • reatmenttoget[.]com
  • ndingcouncern[.]com
  • andingswon[.]com
PDFunk POST request

Fun fact is that, the payload is being encrypted exactly the same way as in the main.js file (even the same RC4 key lol). By decrypting the payload you can get something similar to this:

Payload sent by PDFunk

Unfortunately all I could get back from the C2 servers is this:

PDFunk server response

 Without further static analysis of the Electron V8 bytecode I'm at the dead end.

Key takeaways for Blue Teams

There are couple of things you can search for in your environment to hunt for such threat:
  • General
    • msedgewebview2.exe created by a suspicious process,
    • msedgewebview2.exe created with unusual --user-data-dir or --webview-exe-name parameters,
    • Suspicious remote connections initiated by msedgewebview2.exe,
    • Suspicious Electron (.asar) applications making remote connections,
    • Processes other than Chrome or Edge modifying Secure Preferences.
  • PdfConverters/PDFunk specific
    • Search for any connections to the mentioned domains.
    • User-Agent containing PDFunk keyword.
    • Presence of %TEMP%\.net\PdfConverters and %LocalAppData%\Programs\PDFunk\ directories.
    • Presence of PDFunk.lnk in the Startup folder.
Depending on the size of your environment filtering out all the noise might be tricky, but the hunting is about looking for anomalies (the famous needle in a haystack). Happy hunting!

Appendix

It seems that the attackers, to gain some credibility, created pdfunk[.]com where you can download the application. The main difference is that this variant does not contain the malicious V8 bytecode included. 

Update 16 Nov 2023

Luke Acha posted new set of C2 servers PDFunk is communicating with.

Comments

Popular posts from this blog

Decoding SmartAssembly 8 obfuscation

When compiling an application in the .NET framework, the source code is being compiled into Common Intermediate Language. Then, at runtime, the CIL code is passed through a Just In Time Compiler which translates it into the machine code. The problem is that the CIL can be very easily decompiled back (using apps like dnSpy, .NET Reflector or IlSpy) to the original source code of the application.  To protect intellectual property and the source code, the applications should be somehow obfuscated. There are multiple tools which can help you with that. One of them is SmartAssembly SmartAssembly is a commercial .NET obfuscator created by Redgate. As the website says: ... [It] helps protect your application against reverse-engineering or modification, by making it difficult for a third-party to access your source code. Malware authors take advantage of the .NET framework and its compatibility with Windows environment, however they also need to protect their code to be as successful as possib