While investigating a sophisticated phishing attack1Based on the domains used (see IOCs below) appearing in this automated analysis, it seems likely the campaign is using the Tycoon 2FA phishing kit. targeting affiliates of a major American political action committee (PAC) in early January 2025, Juniper Threat Labs observed a new JavaScript obfuscation technique. This technique was first described by a security researcher on X back in October 2024, highlighting the speed with which offensive security research can be incorporated into real-world attacks. In this post, we’ll describe this technique and provide some short code snippets that defenders can use while reverse-engineering attacks.
On October 8, 2024, Martin Kleppe first demonstrated this technique via a post on X. A refinement of the technique, which was used verbatim in the phishing attack, was posted on October 28 and is demonstrated at https://aem1k.com/invisible/encoder/. The encoding works by using two different Unicode filler characters, the Hangul half-width and the Hangul full width, to represent the binary values 0 and 1, respectively. Each group of 8 of these characters forms a single byte, representing an ASCII character. The entire payload sits invisibly in a script as a property, but is executed with a short bootstrap code when the property is accessed through a Proxy get() trap.

To safely recover the encoded JavaScript, the following Python function takes a Unicode string of Hangul filler characters and converts it back to visible text.
# Take a file containing a string of Hangul filler characters # and convert it back to a string of JavaScript code. No error # checking! def decode_invisible(fname): with open(fname, mode='r', encoding='utf-8') as f: invisible_string = f.read() # Convert the invisible string to a list of integers vals = [] for i in range(len(invisible_string)//8): n = 0 # convert each 8 character sequence to a byte value for c in invisible_string[i*8:(i+1)*8]: # half width hangul character if c == '\uFFA0': n = n * 2 # full width hangul character elif c == '\u3164': n = n * 2 + 1 vals.append(n) # convert the list of bytes to a string return "".join(chr(x) for x in vals)
Interestingly, the portion of the attack using invisible JavaScript was itself embedded in another script as a base64-encoded string, which produced a peculiar sequence of base64 characters:

In addition to the invisible JavaScript, we observed other indications this was a sophisticated phishing attempt. The attacks were highly personalized, including non-public information, and the initial JavaScript would try to invoke a debugger breakpoint if it were being analyzed, detect a delay, and then abort the attack by redirecting to a benign website.

The initial phishing links were wrapped recursively in Postmark tracking links, obscuring the final destination.

These links can be unraveled with the following Python code:
import re from urllib.parse import unquote LINK_RE = r'(?:https://)?click.pstmrk.it/3s/(.*)/Gnrm/\w+/AQ/[0-9a-f\-]*/1/(?:\w|#)*' def unravel_postmark_link(s): # match a postmark link and capture the url-encoded target in the middle expr = re.compile(LINK_RE) m = expr.match(s) if m: # recurse until we see a non-Postmark link return unravel_postmark_link(unquote(m.group(1))) return s
This attack shows how quickly security research proofs-of-concept are picked up by threat actors. At Juniper Threat Labs, we endeavor to provide accurate descriptions of malicious techniques without providing ready-made attacks. (Though, as we’ve pointed out in the past, LLMs are lowering the barrier to entry for attackers.) We hope that the code snippets above will be useful to other researchers and defenders in the field.
IOCs
veracidep[.]ru
mentespic[.]ru
[1] Based on the domains used (see IOCs) appearing in this automated analysis, it seems likely the campaign is using the Tycoon 2FA phishing kit.