# Deep Analysis of Vidar Information Stealer **eln0ty.github.io/malware analysis/vidar/** 17 minute read Vidar (forked from Arkei info stealer) is very popular info stealer written in C++. **What does it steal?** The malware has all the kinds of classic features of stealers: Stealing browser Data (auto-fill, history, cookies - credit cards) Stealing Crypto mining wallets Stealing data from 2FA software like Authy Searching for specific documents Telegram notifications Screenshot Get a complete snapshot of all information of the computer victim February 6, 2022 Vidar’s clients have access to a C2 Shop portal where they are able to generate their own payloads. So there is no management on their side. For this in-depth analysis, I will inspect the 49.7 version of Vidar. Before starting, I want to thank my friend [@_ n1ghtw0lf because he helped me a lot to write this report..](https://twitter.com/_n1ghtw0lf) Let’s start ^_^ ## Vidar overview **SHA256:** `532BC078A68683CE70CB765191A128FADEE2A23180B1A8E8A16B72F1A8EE291A` I will give a brief overview of how Vidar operates then I will go into details in the upcoming sections. This is the basic config from [Hatching sandbox.](https://tria.ge/220118-alwyesegdk) Vidar collects All important data from victim’s device then Uploads them to C2 server and delete these files from the device with `taskkill.exe` ----- The collection will be something like that (I got it from sandbox so I lost some data because sandbox doesn’t contain everything) compress them in `.zip file to be ready for uploading.` You can watch this [video which describes the operation from server side.](https://vimeo.com/514353794?fbclid=IwAR1PqolWyX-uyF66U2LyY3z5mk7SnIJFKDw00vjbwnAo9LzNfLvS8yaI9iw) ## Sample Preparation (strings & dlls) I faced some problems in my sample, all strings are encrypted and dlls are dynamic allocated. Vidar tries to decrypt it with the first function before starting any process. ----- ## Decrypt strings The encryption algorithm is pretty easy and straight forward. We just do `text = xor(key, cipher)` for every encrypted text by automating it with IDAPython. This is the script for the mission. “Every section of the code has a comment to make it readable for you” ----- ``` import idc def dec_str(key, data, length): res = bytearray() for i in range(length): res.append(key[i] ^ data[i]) return res.decode() start = 0x401301 end = 0x4031E5 ea = start addrs = [] dec = '' key = b'' data = b'' length = 0 while ea <= end: # check if opperand is immediate if idc.get_operand_type(ea, 0) == idc.o_imm: addrs.append((idc.get_operand_value(ea, 0))) # get key, data, length if len(addrs) == 3: length = addrs[0] data = idc.get_bytes(addrs[1], length) key = idc.get_bytes(addrs[2], length) addrs = [] # comment decrypted string if idc.print_insn_mnem(ea) == "call": dec = dec_str(key, data, length) idc.set_cmt(ea, dec, 1) if (idc.print_insn_mnem(ea) == "mov") and (idc.get_operand_type(ea, 0) == idc.o_mem) and (idc.get_operand_type(ea, 1) == idc.o_reg): global_var = idc.get_operand_value(ea, 0) idc.set_name(global_var, "STR_" + dec, SN_NOWARN) # move to next instruction ea = idc.next_head(ea, end) ``` After this step you must see a clear plain text. Here you are the results: Expand to see more INSERT_KEY_HERE JohnDoe HAL9TH api.faceit.com /core/v1/nicknames/ about Mozilla/5.0 (iPhone; CPU iPhone OS 6_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10A5376e Safari/8536.25 C:/ProgramData/ .exe :Zone Identifier ----- [ZoneTransfer] ZoneId=2 Windows ProgramData RECYCLE.BIN Config.Msi System Volume Information msdownld.tmp Recovery Local/Temp Program Files Recycle.Bin All Users MicrosoftEdge/Cookies Users/Public Local/Packages Local/NuGet Roaming/WinRAR Local/Microsoft Microsoft fee_estimates peers mempool banlist governance mncache mnpayments netfulfilled passwords.txt Login Data Cookies Web Data /files/Autofill /files/Cookies /files/CC /files/History /files/Downloads /files/ /files/Files hwid os platform profile user cccount fcount telegram ver ----- vaultcli.dll VaultOpenVault VaultCloseVault VaultEnumerateItems VaultGetItem VaultFree SELECT url FROM moz_places %s/Mozilla/Firefox/profiles.ini /signons.sqlite SELECT encryptedUsername, encryptedPassword, formSubmitURL FROM moz_logins /logins.json formSubmitURL usernameField encryptedUsername encryptedPassword guid SELECT host, name, value FROM moz_cookies SELECT origin_url, username_value, password_value FROM logins SELECT name, value FROM autofill SELECT name_on_card, expiration_month, expiration_year, card_number_encrypted FROM credit_cards SELECT target_path, tab_url from downloads SELECT url, title from urls SELECT HOST_KEY, is_httponly, path, is_secure, (expires_utc/1000000)-11644480800, name, encrypted_value from cookies C:/Users/ /AppData/Roaming/FileZilla/recentservers.xml Soft: FileZilla /AppData/Roaming/.purple/accounts.xml Soft: Pidgin /Thunderbird/Profiles/ C:/Program Files (x86)/Mozilla Thunderbird APPDATA LOCALAPPDATA Thunderbird /files/Telegram /Telegram Desktop/tdata/* D877F783D5D3EF8C* /Telegram Desktop/tdata/ key_datas ----- /Telegram Desktop/tdata/D877F783D5D3EF8C/ map* /Telegram Desktop/tdata/D877F783D5D3EF8C/ firefox.exe plugin-container.exe update_notifier.exe Mozilla Firefox /Mozilla/Firefox/Profiles/ Pale Moon /Moonchild Productions/Pale Moon/Profiles/ Waterfox /Waterfox/Profiles/ Cyberfox /8pecxstudios/Cyberfox/Profiles/ BlackHawk /NETGATE Technologies/BlackHawk/Profiles/ IceCat /Mozilla/icecat/Profiles/ K-Meleon /K-Meleon/ Google Chrome /Google/Chrome/User Data/ Chromium /Chromium/User Data/ Kometa /Kometa/User Data/ Amigo /Amigo/User Data/ Torch /Torch/User Data/ Orbitum /Orbitum/User Data/ Comodo Dragon /Comodo/Dragon/User Data/ Nichrome /Nichrome/User Data/ Maxthon5 /Maxthon5/Users/ Sputnik /Sputnik/User Data/ Epic Privacy Browser /Epic Privacy Browser/User Data/ Vivaldi /Vivaldi/User Data/ CocCoc /CocCoc/Browser/User Data/ URAN ----- /uCozMedia/Uran/User Data/ QIP Surf /QIP Surf/User Data/ Cent Browser /CentBrowser/User Data/ Elements Browser /Elements Browser/User Data/ TorBro Browser /TorBro/Profile/ Suhba Browser /Suhba/User Data/ Mustang Browser /Rafotech/Mustang/User Data/ Chedot Browser /Chedot/User Data/ Brave_Old /brave/ 7Star /7Star/7Star/User Data/ Microsoft Edge /Microsoft/Edge/User Data/ 360 Browser /360Browser/Browser/User Data/ QQBrowser /Tencent/QQBrowser/User Data/ Opera /Opera Software/Opera Stable/ OperaGX /Opera Software/Opera GX Stable/ Local State Cookies %s_%s.txt TRUE FALSE /Microsoft/Windows/Cookies/Low/ Cookies/IE_Cookies.txt /Packages/Microsoft.MicrosoftEdge_8wekyb3d8bbwe/AC/#!001/MicrosoftEdge/Cookies/ Cookies/Edge_Cookies.txt /files/Wallets %USERPROFILE% %DESKTOP% KERNEL32.DLL LoadLibraryA GetProcAddress VirtualAllocExNuma gdi32.dll ole32.dll ----- user32.dll psapi.dll BCRYPT.DLL BCryptCloseAlgorithmProvider BCryptDestroyKey BCryptOpenAlgorithmProvider BCryptSetProperty BCryptGenerateSymmetricKey BCryptDecrypt CRYPT32.DLL CryptUnprotectData CryptStringToBinaryA C:/ProgramData/nss3.dll NSS_Init NSS_Shutdown PK11_GetInternalKeySlot PK11_FreeSlot PK11_Authenticate PK11SDR_Decrypt advapi32.dll RegOpenKeyExA RegQueryValueExA RegCloseKey RegOpenKeyExW RegGetValueW RegEnumKeyExA RegGetValueA GetUserNameA GetCurrentHwProfileA wininet.dll InternetCloseHandle InternetReadFile HttpSendRequestA HttpOpenRequestA InternetConnectA InternetOpenA HttpAddRequestHeadersA HttpQueryInfoA InternetSetFilePointer InternetOpenUrlA InternetSetOptionA DeleteUrlCacheEntry CreateCompatibleBitmap SelectObject BitBlt DeleteObject CreateDCA ----- GetDeviceCaps CreateCompatibleDC CoCreateInstance CoUninitialize GetDesktopWindow ReleaseDC GetKeyboardLayoutList CharToOemA GetDC wsprintfA EnumDisplayDevicesA GetSystemMetrics GetModuleFileNameExA GetModuleBaseNameA EnumProcessModules TronLink /Local Extension Settings/ibnejdfjmmkpcnlpebklmnkoeoihofec/CURRENT /Sync Extension Settings/ibnejdfjmmkpcnlpebklmnkoeoihofec/CURRENT /Local Extension Settings/ibnejdfjmmkpcnlpebklmnkoeoihofec /Sync Extension Settings/ibnejdfjmmkpcnlpebklmnkoeoihofec MetaMask /Local Extension Settings/nkbihfbeogaeaoehlefnkodbefgpgknn/CURRENT /Sync Extension Settings/nkbihfbeogaeaoehlefnkodbefgpgknn/CURRENT /Local Extension Settings/nkbihfbeogaeaoehlefnkodbefgpgknn /Sync Extension Settings/nkbihfbeogaeaoehlefnkodbefgpgknn BinanceChainWallet /Local Extension Settings/fhbohimaelbohpjbbldcngcnapndodjp/CURRENT /Sync Extension Settings/fhbohimaelbohpjbbldcngcnapndodjp/CURRENT /Local Extension Settings/fhbohimaelbohpjbbldcngcnapndodjp /Sync Extension Settings/fhbohimaelbohpjbbldcngcnapndodjp Authenticator /Local Extension Settings/bhghoamapcdpbohphigoooaddinpkbai/CURRENT /Sync Extension Settings/bhghoamapcdpbohphigoooaddinpkbai/CURRENT /Local Extension Settings/bhghoamapcdpbohphigoooaddinpkbai /Sync Extension Settings/bhghoamapcdpbohphigoooaddinpkbai Wallets Plugins *wallet*.dat /Wallets/ keystore Ethereum" /Ethereum/ Electrum /Electrum/wallets/ ElectrumLTC /Electrum-LTC/wallets/ Exodus ----- /Exodus/ exodus.conf.json window-state.json /Exodus/exodus.wallet/ passphrase.json seed.seco info.seco ElectronCash /ElectronCash/wallets/ default_wallet MultiDoge /MultiDoge/ multidoge.wallet JAXX /jaxx/Local Storage/ file__0.localstorage Atomic /atomic/Local Storage/leveldb/ 000003.log CURRENT LOCK LOG MANIFEST-000001 0000* Binance /Binance/ app-store.json Coinomi /Coinomi/Coinomi/wallets/ *.wallet *.config wallet_path SOFTWARE/monero-project/monero-core /Monero/ SELECT fieldname, value FROM moz_formhistory /files/Soft /files/Soft/Authy /Authy Desktop/Local Storage/ /Authy Desktop/Local Storage/*.localstorage /Opera Stable/Local State Let’s move to the next step… ## Building imports Vidar uses `LoadLibraryA &` `GetProcAddress to make a build imports dynamically. The following` function is used for this mission. ----- But there are no readable APIs. So I wrote an IDAPython script to rename it. The script used the **_decrypted strings and map them with the functions to get a clear overview. “you can check it with the_** debugger” ----- ``` import idc start = 0x49978D end = 0x499B62 ea = start api_names = [] while ea <= end: # get GetProcAddress API name if (idc.print_insn_mnem(ea) == "mov") and (idc.get_operand_type(ea, 0) == idc.o_reg) and (idc.get_operand_type(ea, 1) == idc.o_mem): addr = idc.get_operand_value(ea, 1) name = idc.get_name(addr) if name.startswith("STR_"): api_names.append(name) # assign GetProcAddress result to global var if (idc.print_insn_mnem(ea) == "mov") and (idc.get_operand_type(ea, 0) == idc.o_mem) and (idc.print_operand(ea, 1) == "eax"): addr = idc.get_operand_value(ea, 0) name = api_names.pop(0) idc.set_name(addr, "API_" + name[4:]) # move to next instruction ea = idc.next_head(ea, end) ``` Now you can look and enjoy.. ### Imported DLLs Here is a list of imported functions: ----- Expand to see more bcrypt.dll BCryptCloseAlgorithmProvider BCryptDestroyKey BCryptOpenAlgorithmProvider BCryptSetProperty BCryptGenerateSymmetricKey BCryptDecrypt crypt32.dll CryptUnprotectData CryptStringToBinaryA advapi32.dll RegOpenKeyExA RegQueryValueExA RegCloseKey RegOpenKeyExW RegGetValueW RegEnumKeyExA RegGetValueA GetUserNameA GetCurrentHwProfileA wininet.dll InternetCloseHandle InternetReadFile HttpSendRequestA HttpOpenRequestA InternetConnectA InternetOpenA HttpAddRequestHeadersA HttpQueryInfoA InternetSetFilePointer InternetOpenUrlA InternetSetOptionA DeleteUrlCacheEntry gdi32.dll CreateCompatibleBitmap SelectObject BitBlt DeleteObject CreateDCA GetDeviceCaps CreateCompatibleDC ole32.dll CoCreateInstance CoUninitialize user32.dll GetDesktopWindow ----- ReleaseDC GetKeyboardLayoutList CharToOemA GetDC wsprintfA EnumDisplayDevicesA psapi.dll GetModuleFileNameExA GetModuleBaseNameA EnumProcessModules ### Extra DLLs The malware has been observed, upon execution. DLL files are required during the stealing process of different kind of browsers. So it downloads them with connecting to ip: `162.55.213.180 via GET` request. They are deleted when task is done. **DLL** **Description** freebl3.dll Freebl Library for the NSS (Mozilla Browser) mozglue.dll Mozilla Browser Library msvcp140.dll Visual C++ Runtime 2015 nss3.dll Network System Services Library (Mozilla Browser) softokn3.dll Mozilla Browser Library vcruntime140.dll Visual C++ Runtime 2015 Well, Now our sample is ready to reverse its functionalities. Let’s Continue… ## C2 Server C2 IP `162.55.213.180 (real C2)` Vidar has 2 profiles with different websites, every profile should have same IP list. IPs delimited with `|` in each list. So Vidar tries to grep c2 server IP from 1 of them ‘In our case just 1 IP’. you can check profile description First `mastodon.online/@prophef1` ----- Second `koyu.space/@prophef2` Vidar tries to connect with C2 server with it’s hardcoded profile-id to get the right config: ``` 1,1,1,1,1,1,1,1,1,1,250,Default;%DESKTOP%/;/*.txt:/*.dat:/*wallet/*.*:/*2fa/*.*:/*backup/*.*:/*co ``` Each part have the “;” in delimiter, so let’s dig into it. ## How to understand the configuration format In our example, this is the configuration the malware could get from the C2 : **First part** ----- **1** **Saved password** 1 Cookies / AutoFill 1 Wallet 1 Internet History 1 ??? – Supposed to be Skype (not implemented)/ 1 ??? – Supposed to be Steam (not implemented)/ 1 Telegram 1 Screenshot 1 Grabber 1 ??? 250 Max Size (kb) Default Name of the profile (also used for archive file into the files repository) **Second part** **%DESKTOP % –> Selected folder repository where the grabber feature will search recursively (or not)** some selected data **Third part** **_.txt:/.dat:/wallet/./:/2fa/./:/backup/./:/code/./:/password/./:/auth/./:/google/./:/utc/./:/UTC/./:/crypt/./:/key/.*_** **Fourth part** **50** **Max Size per file (kb)** true Collect Recursively **Fifth part** movies:music:mp3; This is the exception part, the grabber will avoid those strings if it matches in the files searched recursively in the specific wanted folder. ## Folder generation To summarize all kind of possibles files/folders that will be generated for the malicious repository is in fact pretty simple : ----- ``` //files Master folder //files//Autofill <- Auto-Fill files //files//CC <- Credit Cards //files//Cookies <- Cookies //files//Downloads <- Downloaded data history from browsers //files//Files <- Profile configs (Archives) //files//History <- Browser histories //files//Soft <- Master folder for targeted softwares //files//Soft//Authy <- 2FA software //files//Telegram <- Telegram messages //files//Wallets <- Cryptomining Wallets ``` General list files ``` //files/screenshot.jpg <- Actual screenshot of the screen //files/passwords.txt <- Passwords consolidated all at once //files//information.txt <- Snapshot of the computer setup //files//outlook.txt <- Outlook cardentials ## Browsers ``` firefox waterfall Cyberfox BlackHawk IceCat Opera OperaGX Chromium Kometa Amigo Torch orbitum Nichrome Maxthon 5 sputnik CocCoc Uran 7Star QQBrowser CryptoTab Browser Brave Brave old Of course, this list could be longer than this if there are some browsers based on chromium repository. ## 2 Factor Authentication software (2FA) This technique could be also another door for vulnerabilities because no system is safe and stealing it will be more and more common in the future. So with Vidar, the Authy software is targeted. ----- More specifically the SQLite file on the corresponding application on %APPDATA% repository. So guys don’t fully trust a system even security system. Give your privacy all your care. ## Messengers ----- **outlook** Here is the data that Vidar steals : extracted from sandbox machine **Thunderbird** **Telegram** I won’t describe how Vidar steals them because the process (in-depth)is painful and needs another report to explain. :) ## Crypto Wallets Eletcrum Exodus ElectronCash MultiDoge JAXX Atomic Binance This list could change if the customer added some additional files to search for specific areas on victim’s machine. ## Information log ----- to understand how this file is generated with the corresponding API call, breakpoint on these API if you want to take your time to analyze all the step easily. Vidar steals almost all general information about victim machine and save it in inforamtion.txt file like: Date Machine ID GUID HWID Path Work DIR ) Get the name of the operating system and platform is classic because this is, in fact, a concatenation of [two things. First, Vidar check if Windows is 32 or 64-bit, it checks itself if is running on WOW64 with the](https://docs.microsoft.com/fr-fr/windows/desktop/WinProg64/running-32-bit-applications) [help of IsWow64Process.](https://docs.microsoft.com/en-us/windows/desktop/api/wow64apiset/nf-wow64apiset-iswow64process) ----- Second, with [RegOpenKeyExA, the value of this registry key is fetched:](https://docs.microsoft.com/en-us/windows/desktop/api/winreg/nf-winreg-regopenkeyexa) ``` HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Windows NT/CurrentVersion/ProductName ``` Here we can see the some pretty APIs that we decrypted before analysis. Let’s continue our analysis… Windows version Computer Name User Name Display Resolution Display Language Keyboard Languages Local Time TimeZone [Hardware] -> Processor -> CPU Count -> RAM -> VideoCard ----- [[Processes] Get a snapshot from all processes executed using CreateToolhelp32Snapshot &](https://docs.microsoft.com/en-us/windows/desktop/api/tlhelp32/nf-tlhelp32-createtoolhelp32snapshot) **_[Process32First &](https://docs.microsoft.com/en-us/windows/desktop/api/tlhelp32/nf-tlhelp32-process32first)_** **_[Process32Next](https://docs.microsoft.com/en-us/windows/win32/api/tlhelp32/nf-tlhelp32-process32next)_** After, checking if it’s a parent process or a child process, Vidar will grab two value of the **_[PROCESSENTRY32 object : th32ProcessID: PID szExeFile: The name of the PE](https://docs.microsoft.com/fr-fr/windows/desktop/api/tlhelp32/ns-tlhelp32-tagprocessentry32)_** I can’t screen all function here but you can take your time while analyzing it. Let’s continue… [Software] Get list of all installed software on the machine, the value of this registry key is fetched: ``` HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Windows/CurrentVersion/Uninstall ``` These values are retrieves of each software (DisplayName & DisplayVersion) ----- ## Result [You can see into sandbox analysis, the generated information.txt and the whole process and](https://app.any.run/tasks/0a57b362-32d4-4d33-bf66-9107ac1ca39d) connections. ----- ``` Version: 49.7 Date: Tue Feb 01 04:37:51 2022 MachineID: 90059c37-1320-41a4-b58d-2b75a9850d2f GUID: {e29ac6c0-7037-11de-816d-806e6f6e6963} HWID: 90059c37-1320-41a4-b58d-816d-806e6f6e6963 Path: C:/Users/admin/AppData/Local/Temp/vidar.exe Work Dir: C:/ProgramData/GI3PPKTM8AJDIRUF0RKXBSEQV Windows: Windows 7 Professional [x86] Computer Name: USER-PC User Name: admin Display Resolution: 1280x720 Display Language: en-US Keyboard Languages: English (United States) Local Time: 1/2/2022 4:37:51 TimeZone: UTC-0 [Hardware] Processor: Intel(R) Core(TM) i5-6400 CPU @ 2.70GHz CPU Count: 4 RAM: 3583 MB VideoCard: Standard VGA Graphics Adapter [Processes] ---------- System [4] ------------------------------ smss.exe [260] - csrss.exe [544] - vidar.exe [1988] < ... > [Software] VLC media player [3.0.11] WinRAR 5.91 (32-bit) [5.91.0] < ... > ## Other payloads ``` [Vidar can download an executable file and execute it with ShellExecuteA.](https://docs.microsoft.com/en-us/windows/win32/api/shellapi/nf-shellapi-shellexecutea) First Download ----- Then Execute ## Kill Task Vidar uses taskkill.exe to kill process. So when all the task of the stealer is finally accomplished and [cleaned, the stealer needs to erase itself. So first of all, it retrieves its own PID with the help of](https://en.wikipedia.org/wiki/Process_identifier) [GetCurrentProcessId.](https://docs.microsoft.com/en-us/windows/desktop/api/processthreadsapi/nf-processthreadsapi-getcurrentprocessid) ----- [When the request is finely crafted, Vidar is simply using ShellExecuteA to pop a command shell and](https://docs.microsoft.com/en-us/windows/desktop/api/shellapi/nf-shellapi-shellexecutea) execute the task, this erases all trace of the interaction of the payload on the machine and delete all downloaded DLLs. The full command: ``` "C:/Windows/System32/cmd.exe" /c taskkill /im vidar.exe /f & timeout /t 6 & del /f /q "C:/Users/admin/AppData/Local/Temp/vidar.exe" & del C:/ProgramData/*.dll & exit ## Exfiltration ``` **File Generation** I can’t understand well how malware generates the file name but It consists from ‘Machine ID + ?? (random digits) + .zip ‘ ----- This at least, all the different Content-Disposition that will be added to the HTTP request. **hwid** **Hardware ID** os Operating System platform 32 or 64 bits System profile C2 Profile ID user Name of the victim account cccount Number of Credit Cards stolen ccount Number of Coins Stolen (CryptoWallet) fcount Number of files stolen ver The version of the Vidar malware ## Conclusion Vidar always tries to steal your data as much as it can and its tasks vary from version to another. It was hard and exciting and I want to mention “This is my first Tech. report” and I will write more and more. [Finally, Remember you can watch the video that I passed in the intro to see how it works from server](https://vimeo.com/514353794?fbclid=IwAR1PqolWyX-uyF66U2LyY3z5mk7SnIJFKDw00vjbwnAo9LzNfLvS8yaI9iw) side. ----- ## Yara Rules ``` rule Vidar_Stealer : Vidar { meta: Author = "eln0ty" Description = "Rule to detect Vidar" Date = "Feb 5, 2022" strings: $mz = "MZ" $s1 = "1BEF0A57BE110FD467A" ascii $s2 = "Version: %s" ascii $s3 = "Date: %s" ascii $s4 = "MachineID: %s" ascii $s5 = "GUID: %s" ascii $s6 = "HWID: %s" ascii condition: ($mz at 0) and (all of ($s*)) } ``` -----