Recently, various industry and media sources have publicly reported that OceanLotus, a suspected Vietnam state-sponsored adversary, has conducted multiple targeted intrusions against auto manufacturers. This post examines a second-stage tool, JEShell, used during one such intrusion.
JEShell contains code-level overlaps with the OceanLotus KerrDown malware first publicly described in a Medium post and a Palo Alto Unit42 post. At a high level, JEShell is functionally similar to the KerrDown malware: both families decode and run layers of shellcode with the intention of downloading or directly installing a Cobalt Strike Beacon implant. Unlike KerrDown (a Windows DLL), JEShell is written in Java. JEShell is delivered alongside (rather than instead of) KerrDown and other implants and in some cases shares the same C2, likely as a measure of redundancy for the attacker.
This post examines one of two identified JEShell hashes:
The other known file, not examined in this post, is:
JEShell contains an encrypted resources with a randomized named and an XOR key (different between samples) used to decode it. The XOR is performed in a rolling fashion using a “mod” function: the first byte of the encrypted resource is XORed by the byte representation of the first character of the key, the second byte by the second character, and so on. When the end of the key is reached, it returns to the first letter. By doing this, the authors ensure that the decoded resource is not revealed or detected by a brute force mechanism.
The resource is decoded into a byte array and loaded into memory through one of two workflows. On a 32-bit system, the resource is injected into the memory of the currently running process (Java.exe). On a 64-bit system a process is randomly selected and created from a hardcoded list and the array is injected into that process. The process list used on 64-bit systems in this sample is:
“C:\\Windows\\SysWOW64\\ARP.exe”, “C:\\Windows\\SysWOW64\\at.exe”, “C:\\Windows\\SysWOW64\\auditpol.exe”, “C:\\Windows\\SysWOW64\\bitsadmin.exe”, “C:\\Windows\\SysWOW64\\bootcfg.exe”, “C:\\Windows\\SysWOW64\\ByteCodeGenerator.exe”, “C:\\Windows\\SysWOW64\\cacls.exe”, “C:\\Windows\\SysWOW64\\chcp.com”, “C:\\Windows\\SysWOW64\\CheckNetIsolation.exe”, “C:\\Windows\\SysWOW64\\chkdsk.exe”, “C:\\Windows\\SysWOW64\\choice.exe”, “C:\\Windows\\SysWOW64\\cmdkey.exe”, “C:\\Windows\\SysWOW64\\comp.exe”, “C:\\Windows\\SysWOW64\\diskcomp.com”, “C:\\Windows\\SysWOW64\\Dism.exe”, “C:\\Windows\\SysWOW64\\esentutl.exe”, “C:\\Windows\\SysWOW64\\expand.exe”, “C:\\Windows\\SysWOW64\\fc.exe”, “C:\\Windows\\SysWOW64\\find.exe”, “C:\\Windows\\SysWOW64\\gpresult.exe”
The injected shellcode contains multiple layers. The first layer dynamically resolves APIs and decodes a second layer (a previous post contains suggestions on analyzing shellcode), writing this to a section of virtual memory and executing it with the Kernel32.CreateThread Windows API call:
The second layer of shellcode behaves similarly: it decrypts (via CryptDecrypt) a copy of the Cobalt Strike Beacon implant into memory that is configured with a modified version of a malleable C2 profile.