Agent Tesla Malware Analysis

MD5: 04f44a0cce98b16a0c4154119ff88cd6

Download: https://malshare.com/sample.php?action=detail&hash=02a690404a3d82ed7aef87f8518cac02809384d6b0550a36fc837c8552255d3d

Link: https://app.any.run/tasks/518958b9-4306-42cb-b525-214a942050ad/

dynamic analysis

Let’s analyze a sample which are ranked 1st for this week in any.run, with last attack today 21/2 and has been compiled Wed Feb *21 12:29:54 2024*

../_images/Screenshot_127.png

The file comes named as BL-SHIPPING INVOICE.exe and it is a 32-bit .NET file

../_images/Screenshot_226.png

Let’s spin up our Dynamic analysis setup with procmon+procdot / process hacker / fakenet / regshot / wireshark

It spawns some threads of itself

../_images/Screenshot_716.png ../_images/Screenshot_420.png

In fakenet it goes example.com (why?!) , and ipify to get my public ip address ,Then it dns queries mail.2sautomobile.com ??!

../_images/Screenshot_520.png ../_images/Screenshot_618.png

and when i restart the machine i get those two processes spawned which have same sha256 as original malware (maybe some persistance deployed)

../_images/Screenshot_88.png

In procdot+procmon we see it creates file Zmbgisvguo.exe in appdata/roaming and puts it in the run registry , same way as HroxB.exe

../_images/Screenshot_97.png ../_images/Screenshot_108.png ../_images/Screenshot_1111.png

Code analysis

let’s go into dnspy, it just send a post to http://www.example.com/recepticle.aspx and does nothing with the response, it does that a few times maybe to create noise we can ignore them

../_images/Screenshot_128.png

Then it loads array from resources, reverse it , then invoke (run) ExcludeToken method

../_images/Screenshot_137.png

So let’s dump the array reversed

../_images/Screenshot_146.png

Second stage

the other file sha256:0E950415034458215DF5DE5084CBD5AC18DDF5921E64E8037783A4AA6289DB13

it is also 32-bit .NET but its a dll

../_images/Screenshot_156.png

What came out was a mess in dnspy couldn’t understand the functionality, when i even went the invoked method was empty

../_images/Screenshot_166.png

I ran net reactor slayer on it, and deobfuscated successfully

../_images/Screenshot_505.png

and then get the binary from resources and fix it

../_images/Screenshot_5110.png

But i resorted to running the malware, and then running hollows_hunter to get the binary from memory and dump it

the new file sha256:1371BE6A1BDD10F8D0EA4EABD20453F80419B1C412B73555C113473B27373E9D

../_images/Screenshot_176.png

and ran de4dot on it and .net reactor slayer

../_images/Screenshot_186.png

and we got almost clean sample

../_images/Screenshot_196.png

now onto main function, the binary is full of these jumps and conditions for obfuscation

../_images/Screenshot_205.png
following kyG.smethod_0(); it is also bunch of if conditions and jumps, lets go step by step
First it checks if there is any processes with same name and kills it except itself
../_images/Screenshot_2111.png

Configuration extraction

Then calls HobCHX.smethod_0(); which gets bunch of my hardware and computer info and ip

../_images/Screenshot_227.png ../_images/Screenshot_235.png

and sets some configurations, notice there is an email there maybe send my info to that email ? but it seems legit site i don’t know

../_images/Screenshot_246.png
        public static bool EnableKeylogger = Convert.ToBoolean("false");

        // Token: 0x0400000F RID: 15
        public static bool EnableScreenLogger = Convert.ToBoolean("false");

        // Token: 0x04000010 RID: 16
        public static bool EnableClipboardLogger = Convert.ToBoolean("false");

        // Token: 0x04000011 RID: 17
        public static bool EnableTorPanel = Convert.ToBoolean("false");

        // Token: 0x04000012 RID: 18
        public static bool EnableCookies = Convert.ToBoolean("false");

        // Token: 0x04000013 RID: 19
        public static bool EnableContacts = Convert.ToBoolean("false");

        // Token: 0x04000014 RID: 20
        public static bool DeleteBackspace = Convert.ToBoolean("false");

        // Token: 0x04000015 RID: 21
        public static int TorPid = 0;

        // Token: 0x04000016 RID: 22
        public static int KeyloggerInterval = Convert.ToInt32("20");

        // Token: 0x04000017 RID: 23
        public static int ScreenInterval = Convert.ToInt32("20");

        // Token: 0x04000018 RID: 24
        public static int LogType = Convert.ToInt32("1");

        // Token: 0x04000019 RID: 25
        public static bool SmtpSSL = Convert.ToBoolean("true");

        // Token: 0x0400001A RID: 26
        public static int SmtpPort = Convert.ToInt32("587");

        // Token: 0x0400001B RID: 27
        public static bool SmtpAttach = Convert.ToBoolean("false");

        // Token: 0x0400001C RID: 28
        public static string SmtpServer = "mail.2sautomobile.com";

        // Token: 0x0400001D RID: 29
        public static string SmtpSender = "contact@2sautomobile.com";

        // Token: 0x0400001E RID: 30
        public static string SmtpPassword = "Kenzi051008";

        // Token: 0x0400001F RID: 31
        public static string SmtpReceiver = "contact@2sautomobile.com";

        // Token: 0x04000020 RID: 32
        public static bool AppAddStartup = Convert.ToBoolean("true");

        // Token: 0x04000021 RID: 33
        public static bool HideFileStartup = Convert.ToBoolean("false");

        // Token: 0x04000022 RID: 34
        public static string AppStartupFullPath = "";

        // Token: 0x04000023 RID: 35
        public static string StartupDirectoryPath = "";

        // Token: 0x04000024 RID: 36
        public static string StartupEnvName = "appdata";

        // Token: 0x04000025 RID: 37
        public static string StartupDirectoryName = "HroxB";

        // Token: 0x04000026 RID: 38
        public static string StartupInstallationName = "HroxB.exe";

        // Token: 0x04000027 RID: 39
        public static string StartupRegName = "HroxB";

        // Token: 0x04000028 RID: 40
        public static bool DestructionFile = Convert.ToBoolean("true");
    }
}

More functionality

Then it runs cgAknd.FhsFTO() which contains antidebugging

../_images/Screenshot_255.png

Checks if iam a running a host server

../_images/Screenshot_265.png

antidebugging

../_images/Screenshot_275.png

antisandbox (like sandboxie)

../_images/Screenshot_284.png

antiVMs

../_images/Screenshot_295.png

Next it runs MmBwTjUv.smethod_0(); , it is the one setting up run key for the executable

../_images/Screenshot_305.png

Notice that the file names we say above starting after reboot are just random names so we can’t provide that as IOCs

../_images/Screenshot_3111.png

Next it runs MmBwTjUv.smethod_1();, First it creates a directory if not found

../_images/Screenshot_326.png

which is just appdata + HroxB , so the other name Zmbgisvguo is the random one

../_images/Screenshot_336.png ../_images/Screenshot_346.png
AppStartupFullPath contain appdata/roaming/HroxB.exe
It tries to kill all processes with that name
../_images/Screenshot_356.png

Then puts that in run registry

../_images/Screenshot_366.png

Next it runs dPZw6.NTl(); , which runs BtmSV7Q.smethod_0(); into a list that gets enumerated

../_images/Screenshot_376.png

a lot of things are added to the string list, e5B3Ad.l9vHHu appends to a local list

../_images/Screenshot_386.png

1st on the list is Becky! , Which grabs all juicy stuff from the mail client, adds it to the list

../_images/Screenshot_396.png ../_images/Screenshot_405.png

Then openVPN config and Data

../_images/Screenshot_4110.png

Here is the full list it steals data from

PocoMail
Trillian

Psi/Psi+
FTP Navigator
Discord
MysqlWorkbench
IE/Edge
UC Browser
Opera Mail
IncrediMail
Flock Browser
FileZilla
Flash FXP
WS_FTP
FTPGetter
Outlook
Mailbird

ClawsMail
SmartFTP
Becky!

The Bat!
NordVPN
OpenVPN
FtpCommander
Falkon Browser
eM Client
Private Internet Access
DynDns
Safari for Windows
Paltalk
Eudora
JDownloader 2.0
Pidgin
FoxMail
Internet Downloader Manager
Windows Mail App
WinSCP
CoreFTP
QQ Browser

The list is enumerated, then put into string, then send as arguemnt call to function Nc9M4.A9h7JE

../_images/Screenshot_424.png

the function call take another argument first arguemnt which contains my computer info

../_images/Screenshot_465.png

the function call then send all the data as an attachment to the SmtpSender we saw in configuration above

../_images/Screenshot_435.png ../_images/Screenshot_445.png ../_images/Screenshot_455.png

Next is a typical key logger (if enabled)

../_images/Screenshot_475.png ../_images/Screenshot_485.png

Then a screenLogger (if enabled)

../_images/Screenshot_495.png

The End :)

Yara Rules

unpacked

rule AgentTesla
{
    meta:
        description = "AgentTesla unpacked yara"
        author = "abdosalah"

    strings:

        $IOC1  = "Software\OpenVPN-GUI\configs" wide ascii
        $IOC2  = "Software\Qualcomm\Eudora\CommandLine\" wide ascii
        $IOC5  = "HroxB" wide ascii
        $IOC6  = "e6d37ee4-1914-4eb1-8974-e61e8192e837" wide ascii
        $IOC7  = "608d5fdb-93de-4af9-8456-c7c4075a7429" wide ascii
        $IOC8  = "dfcb687e-bb6a-43b0-8540-b98d235b274f" wide ascii
        $IOC9  = "\\.purple\\accounts.xml" wide ascii
        $IOC10 = "SmartFTP\\Client 2.0\\Favorites\\Quick Connect" wide ascii

    condition:
        uint16(0) == 0x5a4d and  (all of ($IOC*))
}

packed

rule AgentTeslaPacked
{
    meta:
        description = "AgentTesla Packed yara"
        author = "abdosalah"

    strings:
        $mz    = { 4D 5A }
        $IOC1  = "http://www.example.com/recepticle.aspx" wide ascii
        $IOC2  = "&thing2=" wide ascii
        $IOC3  = "ExcludeToken" wide ascii
        $IOC4  = { 28 08 00 00 06 13 04 }  #Get the resource Ukhknlmdl

    condition:
        $mz at 0 and  (all of ($IOC*))
}