In this Analysis, we will go over what I saw with my recent deepdive of njRAT.

njRAT

Summary

  1. Victim receives a Phishing Email with malicious Micorsoft Office document attached. The document type can be varied.
  2. Victim opens attached file, and proceeds “enable content” which triggers malicious macro.
  3. It will create C2 connection, which then proceeds to download a PowerShell script if the C2 server is still online.
  4. The script will load malicious code into memory, which will execute the following.
    - Anti-malware Evasion
    - Process Injection of malicious executable.
    - Infosteal

From the next section, I will be sharing what I saw in my analysis and how I approached it.

Hands on Analysis

  1. PowerShell
  2. dnSpy
  3. Text editor

Static Analysis

Code 1

As we can see from the Figure 1 and 2, this script appears to be loading encoded bytes to memory as Assembly code.

Figure 1: Encoded code
Figure 2: Loading raw bytes into memory.

Since the actual code is in memory, we will dump it out to a file for further analysis. We can achieve this by using the following command with PowerShell.

[System.IO.File]::WriteAllBytes(“C:\<Directory>\dump.bin”,[byte[]]$xtz);

Since these codes are written in C#, we will analyze it with dnSpy.

As we can see from Figure 3, the file name appears to be “DECRYPT AES AMSI DLL.”

Figure 3: DECRYPT AES AMSI DLL

The code includes the decrypting method call “AES_Decrypt,” which appears to return the decrypted/decoded string value(?10?) by using key value(?11?).

Figure 4: AES_Decrypt method

Code 2

Next code appears to be loading an ecrypted code into a memory. As we can see from Figure 5 and 6, the code gets decrypted by the method AES_Decrypt from code 1 and gets loaded onto memory.

Figure 5: AES_Decrypt method for decrypting the code
Figure 6: The decrypted code $element is loaded into memory

Lets take a look at the loaded code with dnSpy.
Use same method from Code 1 to dump the code onto disk.

Figure 7: we.dll

From the Figure 7, the decrypted code’s name appears to be “we” and as we have seen in Figure 6, it appears to be calling main method from ANGOLA class. In Figure 8, we can see that the code is loading a library ANGOLA.tLib, which appears to be calling amsi.dll.

Figure 8: Main in we.dll
Figure 9: AMSI library

amsi.dll is a library for Windows Antimalware Scan Interface (AMSI), which is antimalware interface that has functionality of file/memory stream scanning. This interface is integrated with PowerShell, which is used for dynamic evaluation of scripts, interactive mode, or code.

From Figure 8, it appears that the code is patching the amsi.dll with ANGOLA.patchBytes to remove the AMSI functionality and evade the dynamic evaluation before the executions.

Figure 10: Patched bytes for amsi.dll

Code 3

As anti-malware scanning functionality have been removed with code 2, it will load raw bytes onto memory without any encoding or encryption.

Figure 11: Raw byte1
Figure 12: Raw byte2

There appears to be 2 codes that are written in raw bytes and we can see from Figure 13 that the code from Figure 11 is getting loaded onto memory. The code appears to be calling a method jajaja from C3.SYSTEM class and passing arguments RegAsm.exe, Figure 12 code, and NULL.

Figure 13: C3.SYSTEM with method jajaja

To analyze further, lets take a look at C3.SYSTEM in dnSpy. The loaded code’s name appears to be “Managament.inf.”

Figure 14: Managament.inf.dll

The C3.SYSTEM class appears to have static constructor for static data initialization.

Figure 15: Static Constructor SYSTEM()

From Figure 15, the SYSTEM() is altering data SYSTEM.string_0, which is retrieved from method getit(). As we can see from Figure 16, the return value appears to be AssemblyTitle and it appears the author have placed necessary library and function names into AssemblyTitle as suggested by Figure 17.

Figure 16: getit() method
Figure 17: AssemblyTitle with library and function names
Figure 18: smethod_0 method

The constructor appears to be dynamically resolving the library and the functions for this malware to be used. Each libraries are set to delegates and following are the lists.

delegate0_0 : kernel32, CreateProcessA
delegate1_0 : kernel32, GetThreadContext
delegate2_0 : kernel32, Wow64GetThreadContext
delegate3_0 : kernel32, SetThreadContext
delegate4_0 : kernel32, Wow64SetThreadContext
delegate5_0 : kernel32, ReadProcessMemory
delegate6_0 : kernel32, WriteProcessMemory
delegate7_0 : ntdll, ZwUnmapViewOfSection
delegate8_0 : kernel32, VirtualAllocEx
delegate9_0 : kernel32, ResumeThread
Jackpot!

From the above list, it is likely this code executes Process Hollowing Injection.

Since smethod_1 is likely executing process injection, I will not look into every single line of code in this method.

The jajaja function appears to pass the arguments that it retrieved into smethod_1 method within C3.SYSTEM class. From the script in Figure 13, 3 arguments being passed to this method are:

  1. path = C:\Windows\Microsoft.NET\Framework\v4.0.30319\RegAsm.exe
  2. data = Raw Bytes from Figure 12
  3. protect = NULL
Figure 19: jajaja method

In the first IF statement in the smethod_1 appears to be calling the delegate0_0, which is CreateProcessA. The process being created is the RegAsm.exe, which is one arguments from jajaja method.

Figure 20: smethod_1 method calling CreateProcessA in the first IF statement.

CreateProcessA appears to place process information into struct2 and it appears the intptr_0 is a pointer to the handle of RegAsm.exe. Also notice that this process is created in suspended mode, suggested by the sixth parameter 4U.

Figure 21: Struct2 layout

From Figure 22, we can see that it is writing byte_0, which is raw bytes from Figure 12 into process RegAsm.exe and finally in the end it will resume the suspended RegAsm.exe.

Figure 22: delegate6_0 — WriteProcessMemory
Figure 23: delegate9_0 — ResumeThread

From going through the above code, it is evident that this method is utilized to inject raw bytes from Figure 12 into RegAsm.exe. Lets look into the final code.

Injected code waiting to be executed…

Code 4

We will look right into the code via dnSpy. The injected code name appears to be Stub.exe and entrypoint for this code appears to be L.main().

Figure 24: Stub.exe
Figure 25: L.main()

In the Try/Catch, it appears the code creates shorcuts with a name Windows.lnk in template and startup folders for persistence mechanism.

Figure 26: L.RG field

After the creation of the shortcut, it will call ko() method. In the beginning of this method, the string fields are being replaced and reversed, which is likely obfuscation method used by the author.

Figure 27: String Reverse for L.x, L.sf, and L.ss

From the above code the fields are the following.

  • L.sf = Software\Microsoft\Windows\CurrentVersion\Run
  • L.P = 5155
  • L.H = lacraia.hopto[.]org

Soon after the above code, Mutex gets created and it checks whether the executable is already running.

Figure 28: Mutex creation

Code also appears to be retrieving the executable’s information and creating a new thread with L.RC() method.

Figure 29: Retrieving file information and creating a new thread.
Figure 30: L.LO field

The method RC appears to be utilized for C2 communication as we can see from the Figure 31 ~ 33.

Figure 31: TcpClient field L.FCC.
Figure 32: Calls connect method.
Figure 33: connect() method

As we can see from the Figure 33, the method is creating a connection to L.H(lacraia.hopto[.]org) with port(5155), which are reversed field that was retrieved in beginning of ko() method.

After the connection is created, it will send machine’s information to the C2 server via L.inf() method. The following informations are sent.

  • SystemDrive
  • Username
  • Date
  • Windows Version
  • User Role
  • Window Text
  • Version number of executable(this executable appears to be v2.0)

Interesting information was Window Text, where it is retrieved via GetWindowTex() method and this may be one of the anti-analysis method. If we debug this malware with dnSpy, the window name will include “dnSpy” and this may be one way for the malware to distinguish if the malware is running genuinely or not.

Figure 34: Method retrieving Window Text.

Once the connection is established and information is sent to C2 server, it will read the other commands that it receives.

Figure 35: Read received bytes from the connection from C2

Once the command is received, it can be seen that it will start another process with Administrator privilege.

Figure 36: Start new process as an Administrator privilege.

The malware also have capability to take ScreenShots and send it to the C2 server for further information stealing.

Figure 37: Taking screenshots.

It also has capability to erase it’s evidence by deleting Firewall Rule, such as the one we see in Figure 38.

Figure 38: Deleting Firewall Rule

The code has variety of InfoStealing capabilities as we can see from the above analysis and there are more to it that I was not able to go over. I was planning to do Dynamic Analysis, but it appears the server is not available anymore… 😢

However I believe we were able to retrieve plenty of information via Static Analysis since this was C# code, which utilizes Intermediate Language(IL). IL is higher level than x86, allows tools to decompile the code almost close to the original.

Dynamic Analysis

Conclusion

  1. Anti-malware Evasion
  2. Process Injection
  3. Infosteal

The evasion technique that this malware used was interesting. If this malware was regular x86 code and analyze statically via IDA Pro, I would of had harder time analyzing it…However there’s still much to learn…

References

#MalwareAnalysis #ReverseEngineering #Gorilla