Deep Analysis of Mars Stealer By Mohamed Ashraf Published: 2022-05-19 · Archived: 2026-04-05 17:58:13 UTC 28 minute read IntroductionPermalink Mars Stealer is an improved copy of Oski Stealer. I saw alot of tweets recently about it so i decided to write an analysis of the newer version V8. Enjoy reading! Diffrences from the previous version: 1. Anti analysis technique 2. Diffrent encryption algoithm 3. Introudcing new anti debug technique 4. New configuration format 5. External dlls are in one zip file OverviewPermalink https://x-junior.github.io/malware%20analysis/2022/05/19/MarsStealer.html Page 1 of 32 Anti-AnalysisPermalink Opening mars stealer in ida we can see an anti-analysis trick called Opaque Predicates it’s a commonly used technique in program obfuscation, intended to add complexity to the control flow. This obfuscation simply takes an absolute jump (JMP) and transforms it into two conditional jumps (JZ/JNZ). Depending on the value of the Zero flag (ZF), the execution will follow the first or second branch. However, disassemblers are tricked into thinking that there is a fall-through branch if the second jump is not taken (which is impossible as one of them must be taken) and tries to disassemble the unreachable instructions (often https://x-junior.github.io/malware%20analysis/2022/05/19/MarsStealer.html Page 2 of 32 invalid) resulting in garbage code. the deobfuscation is simple, we just need to patch the first conditional jump to an absolute jump and nop out the second jump, we can use IDAPython to achieve this: import idc ea = 0 while True: ea = min(ida_search.find_binary(ea,idc.BADADDR, "74 ? 75 ?",16 ,idc.SEARCH_NEXT | idc.SEARCH_DOWN), # JZ / JN ida_search.find_binary(ea,idc.BADADDR, "75 ? 74 ?",16, idc.SEARCH_NEXT | idc.SEARCH_DOWN)) # JNZ / JZ if ea == idc.BADADDR: break idc.patch_byte(ea, 0xEB) idc.patch_byte(ea+2, 0x90) idc.patch_byte(ea+3, 0x90) idc.patch_byte(ea+4, 0x90) After Running the Script now we can see a clear view , after reversing and renaming First Mars get a handle to kernel32.dll by parsing InLoadOrderModuleList then it passes the handle to a fucntion that loops over the exported functions of the DLL to get the address of the LocalAlloc() and VirtualProtect() functions. https://x-junior.github.io/malware%20analysis/2022/05/19/MarsStealer.html Page 3 of 32 String EncryptionPermalink After that it decrypts some strings used for some checks , the decryption is a simple xor function https://x-junior.github.io/malware%20analysis/2022/05/19/MarsStealer.html Page 4 of 32 We can although see that the xor function is refrenced in another function which i renamed as Decrypt_String_2 if the malware passes the checks which we will see soon it decrypt those string which contanis strings needed for the malware to steal sensitive data . We use idapython script to get those strings and rename the variables to make reversing easier https://x-junior.github.io/malware%20analysis/2022/05/19/MarsStealer.html Page 5 of 32 import string def sanitize_string(name): return "".join([c for c in name if c in string.ascii_letters])[:20].capitalize() def X0r(key, data, length): res = "" for i in range(length): res += chr(key[i] ^ data[i]) return res start_Addrs = [0x00401770,0x00401990 ] end_Addrs = [0x00401967,0x0405444 ] string_list = [] dectypred_data = b'' addrs = [] for i in range(len(start_Addrs)): ea = start_Addrs[i] end = end_Addrs[i] while ea <= end: if idc.get_operand_type(ea, 0) == idc.o_imm: addrs.append((idc.get_operand_value(ea, 0))) if len(addrs) == 3: length = addrs[0] data = idc.get_bytes(addrs[1], length) key = idc.get_bytes(addrs[2], length) dectypred_data = X0r(key, data, length) string_list.append(dectypred_data) addrs = [] https://x-junior.github.io/malware%20analysis/2022/05/19/MarsStealer.html Page 6 of 32 if idc.print_insn_mnem(ea) == "call": idc.set_cmt(ea, dectypred_data, 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" + sanitize_string(dectypred_data), SN_NOWARN) ea = idc.next_head(ea, end) Here is a list of the decrypted strings : Expand to see more   LoadLibraryA   GetProcAddress   ExitProcess   advapi32.dll   crypt32.dll   GetTickCount   Sleep   GetUserDefaultLangID   CreateMutexA   GetLastError Dynamic linkingPermalink The adress of GetProcAddress() and LoadLibraryA() is retrieved by the same method in Dynamic_Linking_1 looping over the exported functions of the kernel32.DLL , then it uses LoadLibraryA() to Load the specified module into the address space and get a handle that get passed to GetProcAddress() to retrieve the address of an exported function from the specified dynamic-link library. Dynamic_Linking_2 is loading the APIs only needed to do some checks if it passes it will load others needed for stealing functionality. https://x-junior.github.io/malware%20analysis/2022/05/19/MarsStealer.html Page 7 of 32 dword_42774 is GetProcAddress() it is called in other function which is Dynamic_Linking_3 that will load other APIs needed for stealing functionality. https://x-junior.github.io/malware%20analysis/2022/05/19/MarsStealer.html Page 8 of 32 We use idapython to rename the global variables with the api name to make reversing easier import idc start_Addrs = [0x00415F86,0x00415FC0 ,0x004161A0 ] end_Addrs = [0x00415FB7,0x00416176,0x00417034] string_list = [] for i in range(len(start_Addrs)): ea = start_Addrs[i] https://x-junior.github.io/malware%20analysis/2022/05/19/MarsStealer.html Page 9 of 32 end = end_Addrs[i] while ea <= end: if (idc.print_insn_mnem(ea) == "push" )and (idc.get_operand_type(ea, 0) == idc.o_imm): name = idc.get_strlit_contents(idc.get_operand_value(ea, 0)).decode() if (idc.print_insn_mnem(ea) == "mov" and (idc.get_operand_type(ea, 0) == idc.o_reg)and (idc.get_operand_ty temp_name = idc.get_name(idc.get_operand_value(ea, 1)) if "Str_" == temp_name[0:4]: name = temp_name[4::] if (idc.print_insn_mnem(ea) == "mov") and (idc.get_operand_type(ea, 0) == idc.o_mem) and (idc.get_operand_t global_var = idc.get_operand_value(ea, 0) idc.set_name(global_var, name, SN_NOWARN) ea = idc.next_head(ea, end) Anti-SandboxPermalink Since a lot of sandboxes hook and bypass Sleep() preventing malware being idle over their execution time. The malware first calls GetTickCount() function that retrieves the number of milliseconds that have elapsed since the system was started, up to 49.7 days, that is our first timestamp. Then calls the Sleep() to suspend itself for 16 seconds. calling GetTickCount() again gets our second timestamp . The malware checks if at least 12 seconds diffrence between the 2 timestampes . If the function returns flase it means that the Sleep() hasn’t been skipped the malware assumes that it is running in a sandbox and exits immediately. Anti-CISPermalink This is one of the easy tricks to check if the malware is not infected users from specific countries. https://x-junior.github.io/malware%20analysis/2022/05/19/MarsStealer.html Page 10 of 32 Mars checks the user language to determine if it’s part of the Commonwealth of Independent States (CIS) countrie it gets the user language ID by using GetUserDefaultLangID and it compares the user language ID to: Language ID Country 0x43F Kazakhstan 0x443 Uzbekistan 0x82C Azerbaijan 0x43Fu Kazakhstan 0x419u Russia 0x423u Belarus If the user language ID matches one of the IDs above, it will exit. Anti-EmulationPermalink If the malware is executed with the computer name HAL9TH and the username with JohnDoe it will exit . This check is done because it is the name given to the Windows Defender Emulator, this technique is used by malware to prevent itself from running in an emulated environment. https://x-junior.github.io/malware%20analysis/2022/05/19/MarsStealer.html Page 11 of 32 MutexPermalink The malware creates a mutex object using CreateMutexA() to avoid having more than one instance running. Then calls GetLastError() which gets the last error, and if the error code is equal to 183 (ERROR_ALREADY_EXIST) it means that mutex already exists and an instance of the malware is already running therefore malware exits. Anti-DebugPermalink The malware create thread that checks BeingDebugged flag which is Special flag in system tables, which dwell in process memory and which an operation system sets, can be used to indicate that the process is being debugged. The states of these flags can be verified either by using specific API functions or examining the system tables in memory. If the malware is being debugged it exits . The thread is going to keep running until the malware finishes excution or the thread end the malware excution if its being debugged . https://x-junior.github.io/malware%20analysis/2022/05/19/MarsStealer.html Page 12 of 32 Expiration checkPermalink The Expiration date variable contains the date 26/04/2022 20:00:00. Mars uses GetSystemTime() to get current system date and time as SYSTEMTIME structe, then calls sscanf() to parse the Expiration date to a SYSTEMTIME structe . SystemTimeToFileTime() take SYSTEMTIME structe as argument then convert it to file time and Expiration date although is converted to file time. If the current time exceedes the Expiration time, the malware calls ExitProcess() to exit immediately. Main FunctionalityPermalink https://x-junior.github.io/malware%20analysis/2022/05/19/MarsStealer.html Page 13 of 32 Mars generate random string that will be the name of the zip file contains stolen data. The communications between c2 and the malware is described as: 1. sends a GET request to the C2 URL on the /RyC66VfSGP.php endpoint to grab its configuration . 2. fetches all DLLs on the /request endpoint, the libraries are zipped 3. Stolen data are posted to the C2 on the same URL used in step 1. Dlls retrieved: DLL Name Description Save path sqlite3.dll Enables SQLite related operations none (mars doesnt write it on disk, parsed from memory) freebl3.dll Library for the NSS (Gecko-based browsers) C:\ProgramData\freebl3.dll mozglue.dll Mozilla Browser Library C:\ProgramData\mozglue.dll msvcp140.dll Visual C++ Runtime 2015 C:\ProgramData\msvcp140.dll nss3.dll Network System Services Library (Gecko-based browsers) C:\ProgramData\nss3.dll softokn3.dll Mozilla Browser Library C:\ProgramData\softokn3.dll vcruntime140.dll Visual C++ Runtime 2015 C:\ProgramData\vcruntime140.dll Another diffrence from the last version is that sqlite3 isnt written on disk, it just get parsed and passed to another function to get handle to it and start loading needed function , the other dll are written . Since the C2 was down i got the pcap from Hatching sandbox. https://x-junior.github.io/malware%20analysis/2022/05/19/MarsStealer.html Page 14 of 32 Understanding Configuration FormatPermalink configuration is base64 encoded MXwxfDF8MXwxfDVxRGxQdVZLb1J8RGlzY29yZHwwfCVBUFBEQVRBJVxkaXNjb3JkXExvY2FsIFN0b3JhZ2VcfCp8MXwwfDB8VGVsZWdyYW1 8MHwlQVBQREFUQSVcVGVsZWdyYW0gRGVza3RvcFx0ZGF0YVx8KkQ4NzdGNzgzRDVEM0VGOEMqLCptYXAqLCpjb25maWdzKnwxfDB8MHw= 1|1|1|1|1|5qDlPuVKoR|Discord|0|%APPDATA%\discord\Local Storage\ |*|1|0|0|Telegram|0|%APPDATA%\Telegram Desktop\tdata\ |*D877F783D5D3EF8C*,*map*,*configs*|1|0|0| https://x-junior.github.io/malware%20analysis/2022/05/19/MarsStealer.html Page 15 of 32 import base64 config = base64.b64decode("MXwxfDF8MXwxfDVxRGxQdVZLb1J8RGlzY29yZHwwfCVBUFBEQVRBJVxkaXNjb3JkXExvY2FsIFN0b3JhZ2VcfCp8 config = config.split("|") print("First Part : \n" ,config[0:6]) print("Second Part :" ) for i in range(6,len(config),7): print(config[i:i+7]) First Part : ['1', '1', '1', '1', '1', '5qDlPuVKoR'] Second Part : ['Discord', '0', '%APPDATA%\\discord\\Local Storage\\', '*', '1', '0', '0'] ['Telegram', '0', '%APPDATA%\\Telegram Desktop\tdata\\', '*D877F783D5D3EF8C*,*map*,*configs*', '1', '0', '0'] First part Config Meaning 1 Downloads_history_Flag 1 Browser_History_Flag 1 Autofill_Flag 1 ScreenShoot_Flag 1 Self_Deletion_Flag 5qDlPuVKoR Explorer Credentials FileName Second part Config Meaning Discord name for the zip file – will contain all the stolen files that related to the current task.so the name for the zip will be name.zip. 0 maybe max size (no indecation of use) %APPDATA%\discord\Local Storage\ An environment variable name and folder name – a starting point for the recursive Grabber. * A regex list – contains multiply parameters that are separated by “,” each one of them is a regex that represents a file type. 1 is_Recursive 0 Write to zip enabled if 0 https://x-junior.github.io/malware%20analysis/2022/05/19/MarsStealer.html Page 16 of 32 Config Meaning 0 Exclusion List GrabberPermalink lets dig into Config_Grabber function to see how you it works after receiving the config we can see the it has a lot of | so it split the config with | delimiter and loop through the splited config. the first part enables/disable some of the stealer functionality then it starts in part 2 which start grapping files wanted. as example [‘Discord’, ‘0’, ‘%APPDATA%\discord\Local Storage\’, ‘*’, ‘1’, ‘0’, ‘0’] it start recurseively grabbing all files in discord\\Local Storage\\ under %APPDATA% and put them in discord.zip If there is more than one regex as in [‘Telegram’, ‘0’, ‘%APPDATA%\Telegram Desktop\tdata\’, ‘D877F783D5D3EF8C,map,configs’, ‘1’, ‘0’, ‘0’] it loops through them and call Recursive_Grabber with each regex . https://x-junior.github.io/malware%20analysis/2022/05/19/MarsStealer.html Page 17 of 32 BrowsersPermalink Mars steals credentials from browsers by static paths. It has four different methods to steal data from different types of browses, like Gecko-based browsers, Opera, Internet Explorer and Chromium-based browsers. https://x-junior.github.io/malware%20analysis/2022/05/19/MarsStealer.html Page 18 of 32 All the extraction functions have the same scheme: 1. The malware saves the addresses of the functions from sqlite3.dll sqlite3_open sqlite3_prepare_v2 sqlite3_step sqlite3_column_bytes https://x-junior.github.io/malware%20analysis/2022/05/19/MarsStealer.html Page 19 of 32 sqlite3_column_blob sqlite3_column_text sqlite3_column_finalize sqlite3_column_close 2. It generates a random string (length of 8 characters) and copies the DB file to a temp folder named like the random string – all the extractions methods will be on the copied DB. In order to extract the data from the DB, the malware has to create the SQL query and query the DB using sqlite3.dll functions. 3. The malware opens the DB by using sqlite3_open and passes the DB path. 4. It calls to sqlite3_prepare_v2, the function gets a handle to DB and the SQL query and returns a statement handle. 5. By using sqlite3_column_bytes/sqlite3_column_blob/sqlite3_column_text, the malware can get the results from the queries 6. The Credentials in Chromium-based browsers DB are encrypted by DPAPI and, therefore, the malware uses the function CryptUnprotectData to decrypt the Credentials. Mars steals information from the Windows Vault, which is the default storage vault for the credential manager information. This is done through the use of Vaultcli.dll, which encapsulates the necessary functions to access the Vault. The malware loops through its items using: VaultEnumerateVaults VaultOpenVault VaultEnumerateItems VaultGetItem VaultFree Targeted DB FilesPermalink File Name Affected Software History Chromium-based browsers Login Data Chromium-based browsers Cookies Chromium-based browsers Web Data Chromium-based browsers formhistory.sqlite Gecko-based browsers cookies.sqlite Gecko-based browsers signongs.sqlite Gecko-based browsers places.sqlite Gecko-based browsers Queries UsedPermalink https://x-junior.github.io/malware%20analysis/2022/05/19/MarsStealer.html Page 20 of 32 Query Target Browser Enabled SELECT target_path, tab_url from downloads chromium , opera by default this feature is disabled, enabled if Downloads_history_Flag is set to 1 SELECT name, value FROM autofill chromium , opera by default this feature is disabled, enabled if Autofill_Flag is set to 1 SELECT url FROM urls chromium , opera by default this feature is disabled,enabled if Browser_History_Flag is set to 1 SELECT action_url, username_value, password_value FROM logins chromium , opera enabled by default SELECT HOST_KEY, is_httponly, path, is_secure, (expires_utc/1000000)-11644480800, name, encrypted_value from cookies chromium , opera enabled by default SELECT name_on_card, expiration_month, expiration_year, card_number_encrypted FROM credit_cards chromium , opera enabled by default SELECT host, isHttpOnly, path, isSecure, expiry, name, value FROM moz_cookies gecko enabled by default SELECT url FROM moz_places gecko by default this feature is disabled,enabled if Browser_History_Flag is set to 1 SELECT fieldname, value FROM moz_formhistory gecko enabled by default Cryptocurrency Wallets via browser extensionsPermalink Mars appears to also target additional Chrome-based browser extensions related to two-factor authentication (2FA) . https://x-junior.github.io/malware%20analysis/2022/05/19/MarsStealer.html Page 21 of 32 Mars steal files from 3 folders : 1. \Local Extension Settings\Extension ID from Google Store 2. \Sync Extension Settings\ Extension ID from Google Store 3. \IndexedDB\Domain Name.indexeddb.leveldb as example if the victim uses Google Chrome with a crypto browser wallet extension, the extension files will be stored in: C:\Users\Username\AppData\Local\Google\Chrome\User Data\Default\Local Extension Settings\Extension ID from Google Store C:\Users\Username\AppData\Local\Google\Chrome\User Data\Default\Sync Extension Settings\ Extension ID from Google Store C:\Users\Username\AppData\Local\Google\Chrome\User Data\Default\IndexedDB\Domain Name.indexeddb.leveldb Type Extension name Extension id Crypto TronLink ibnejdfjmmkpcnlpebklmnkoeoihofec Crypto MetaMask nkbihfbeogaeaoehlefnkodbefgpgknn Crypto Binance Chain Wallet fhbohimaelbohpjbbldcngcnapndodjp Crypto Yoroi ffnbelfdoeiohenkjibnmadjiehjhajb Crypto Nifty Wallet jbdaocneiiinmjbjlgalhcelgbejmnid Crypto Math Wallet afbcbjpbpfadlkmhmclhkeeodmamcflc Crypto Coinbase Wallet hnfanknocfeofbddgcijnmhnfnkdnaad Crypto Guarda hpglfhgfnhbgpjdenjgmdgoeiappafln Crypto EQUAL Wallet blnieiiffboillknjnepogjhkgnoapac https://x-junior.github.io/malware%20analysis/2022/05/19/MarsStealer.html Page 22 of 32 Type Extension name Extension id Crypto Jaxx Liberty cjelfplplebdjjenllpjcblmjkfcffne Crypto BitApp Wallet fihkakfobkmkjojpchpfgcmhfjnmnfpi Crypto iWallet kncchdigobghenbbaddojjnnaogfppfj Crypto Wombat amkmjjmmflddogmhpjloimipbofnfjih Crypto MEW CX nlbmnnijcnlegkjjpcfjclmcfggfefdm Crypto GuildWallet nanjmdknhkinifnkgdcggcfnhdaammmj Crypto Saturn Wallet nkddgncdjgjfcddamfgcmfnlhccnimig Crypto Ronin Wallet fnjhmkhhmkbjkkabndcnnogagogbneec Crypto NeoLine cphhlgmgameodnhkjdmkpanlelnlohao Crypto Clover Wallet nhnkbkgjikgcigadomkphalanndcapjk Crypto Liquality Wallet kpfopkelmapcoipemfendmdcghnegimn Crypto Terra Station aiifbnbfobpmeekipheeijimdpnlpgpp Crypto Keplr dmkamcknogkgcdfhhbddcghachkejeap Crypto Sollet fhmfendgdocmcbmfikdcogofphimnkno Crypto Auro Wallet cnmamaachppnkjgnildpdmkaakejnhae Crypto Polymesh Wallet jojhfeoedkpkglbfimdfabpdfjaoolaf Crypto ICONex flpiciilemghbmfalicajoolhkkenfel Crypto Nabox Wallet nknhiehlklippafakaeklbeglecifhad Crypto KHC hcflpincpppdclinealmandijcmnkbgn Crypto Temple ookjlbkiijinhpmnjffcofjonbfbgaoc Crypto TezBox mnfifefkajgofkcjkemidiaecocnkjeh Crypto Cyano Wallet dkdedlpgdmmkkfjabffeganieamfklkm Crypto Byone nlgbhdfgdhgbiamfdfmbikcdghidoadd Crypto OneKey infeboajgfhgbjpjbeppbkgnabfdkdaf Crypto LeafWallet cihmoadaighcejopammfbmddcmdekcje Crypto DAppPlay lodccjjbdhfakaekdiahmedfbieldgik https://x-junior.github.io/malware%20analysis/2022/05/19/MarsStealer.html Page 23 of 32 Type Extension name Extension id Crypto BitClip ijmpgkjfkbfhoebgogflfebnmejmfbml Crypto Steem Keychain lkcjlnjfpbikmcmbachjpdbijejflpcm Crypto Nash Extension onofpnbbkehpmmoabgpcpmigafmmnjhl Crypto Hycon Lite Client bcopgchhojmggmffilplmbdicgaihlkp Crypto ZilPay klnaejjgbibmhlephnhpmaofohgkpgkd Crypto Coin98 Wallet aeachknmefphepccionboohckonoeemg 2FA Authenticator bhghoamapcdpbohphigoooaddinpkbai 2FA Authy gaedmjdfmmahhbjefcbgaolhhanlaolb 2FA EOS Authenticator oeljdldpnmdbchonielidgobddffflal 2FA GAuth Authenticator ilgcnhelpchnceeipipijaljkblbcobl 2FA Trezor Password Manager imloifkgjagghnncjkhggdhalmcnfklk Crypto WalletsPermalink Mars does not just stop at targeting crypto currencies via browser extensions. Many people prefer not to use third-party applications and services to store their digital currency. Mars will go through various folders looking for specific files related to cryptocurrency. The first paramter detmerines the path if 0 then it’s under %appdata% if 1 it’s under %localappdata% then it search for other wallets with regex *wallet*.dat under %appdata% https://x-junior.github.io/malware%20analysis/2022/05/19/MarsStealer.html Page 24 of 32 Mars have dedicated functionality to target the following crypto wallets: Wallet name Wallet folder Regex Ethereum %appdata%\Ethereum\ keystore Electrum %appdata%\Electrum\wallets\ . Electrum LTC %appdata%\Electrum-LTC\wallets\ . Exodus %appdata%\Exodus\ exodus.conf.json, window-state.json, \Exodus\exodus.wallet\, passphrase.json, seed.seco, info.seco Electron Cash %appdata%\ElectronCash\wallets\ default_wallet MultiDoge %appdata%\MultiDoge\ multidoge.wallet Jaxx %appdata%\jaxx\Local Storage\ file__0.localstorage Atomic %appdata%\atomic\Local Storage\leveldb\ 000003.log, CURRENT, LOCK, LOG, MANIFEST.000001, 0000* Binance %appdata%\Binance\ app-store.json Coinomi %localappdata%\Coinomi\Coinomi\wallets\ *.wallet, *.config https://x-junior.github.io/malware%20analysis/2022/05/19/MarsStealer.html Page 25 of 32 Wallet name Wallet folder Regex Other wallets %appdata% *wallet*.dat System infoPermalink The malware grabs system info and store it in system.txt file 1. IP and country 2. Working path to EXE file 3. Local time and time zone 4. Language system 5. Language keyboard layout 6. Notebook or desktop 7. Processor model 8. Computer name 9. User name 10. Domain computer name 11. Machine ID 12. GUID 13. Installed software and their versions Mars althouge takes screenshot and then add all stolen files to a zip file which it will exfiltrate back to the c2 and get loader config. LoaderPermalink Malware gets loader config as a response after exfiltrating data. This config looks like download_URL|An environment variable name and folder name |startup_parameter| . After pasring the config Mars calls download_file() function with the url and a path which the file will be saved in . Then calls ShellExecuteExA() to execute executable with give paramters retrieved from the config. https://x-junior.github.io/malware%20analysis/2022/05/19/MarsStealer.html Page 26 of 32 Self DeletionPermalink https://x-junior.github.io/malware%20analysis/2022/05/19/MarsStealer.html Page 27 of 32 Malware gets the path to itself by using GetModuleFileName() and calls ShellExecuteExA() which executes the following command "C:/Windows/System32/cmd.exe" /c timeout /t 5 & del /f / path_To_file & exit After 5 seconds the executable will be deleted. Generalized idapython Script using patternsPermalink import idautils , idc, idaapi, ida_search, ida_bytes, ida_auto import string seg_mapping = {idaapi.getseg(x).name: (idaapi.getseg(x).start_ea, idaapi.getseg(x).end_ea) for x in idautils.Segments()} start = seg_mapping[0x1][0] end = seg_mapping[0x1][1] def sanitize_string(name): return "".join([c for c in name if c in string.ascii_letters])[:20].capitalize() def Xor(key, data, length): res = "" for i in range(length): res += chr(key[i] ^ data[i]) return res def getData (addr): key_addr = idc.prev_head(addr) https://x-junior.github.io/malware%20analysis/2022/05/19/MarsStealer.html Page 28 of 32 data_addr = idc.prev_head(key_addr) key_length_addr = idc.prev_head(data_addr) length = idc.get_operand_value(key_length_addr, 0) key = idc.get_bytes(idc.get_operand_value(key_addr,0),length) data = idc.get_bytes(idc.get_operand_value(data_addr,0),length) return key , data ,length def rename_APIs(ea,end): func_addr = ea for i in range(20): if (idc.print_insn_mnem(ea) == "push" )and (idc.get_operand_type(ea, 0) == idc.o_imm): name = idc.get_strlit_contents(idc.get_operand_value(ea, 0)).decode() break if (idc.print_insn_mnem(ea) == "mov" and (idc.get_operand_type(ea, 0) == idc.o_reg)and (idc.get_operand_ty temp_name = idc.get_name(idc.get_operand_value(ea, 1)) if "Str_" == temp_name[0:4]: name = temp_name[4::] break ea = idc.prev_head(ea) ea = func_addr for i in range(20): if (idc.print_insn_mnem(ea) == "mov") and (idc.get_operand_type(ea, 0) == idc.o_mem) and (idc.get_operand_t global_var = idc.get_operand_value(ea, 0) idc.set_name(global_var, name, SN_NOWARN) return name ea = idc.next_head(ea, end) def API_resolve(start,end): Loadlibrarya_addr = 0x0 GetProcAddress_pattern = "8B 55 ?? 52 8B 45 ?? 8B 4D ?? 8B 55 ?? 03 14 ?? 52 E8 ?? ?? ?? ?? 83 C4 ?? 85 C0 75 GetProcAddress_addr = ida_search.find_binary(start, end, GetProcAddress_pattern, 16, idc.SEARCH_DOWN) GetProcAddress_addr = idaapi.get_func(GetProcAddress_addr).start_ea print('[*] Traget fucntion found at {}'.format(hex(GetProcAddress_addr))) for ref in idautils.XrefsTo(GetProcAddress_addr): addr = ref.frm x = rename_APIs(addr, end) if "Loadlibrarya" in x: Loadlibrarya_addr = idc.get_operand_value(idc.next_head(idc.next_head(addr, end), end), 0) new_GetProcAddress_addr = idc.get_operand_value(idc.next_head(idc.next_head(addr, end), end), 0) https://x-junior.github.io/malware%20analysis/2022/05/19/MarsStealer.html Page 29 of 32 for ref in idautils.XrefsTo(new_GetProcAddress_addr): addr = ref.frm rename_APIs(addr, end) for ref in idautils.XrefsTo(Loadlibrarya_addr): addr = ref.frm rename_APIs(addr, end) def Strings_resolve(start,end): xor_pattern = "8b 4d ?? 03 4d ?? 0f be 19 8b 55 ?? 52 e8 ?? ?? ?? ?? 83 c4 ?? 8b c8 8b 45 ?? 33 d2 f7 f1 8b 45 xor_fun_addr = ida_search.find_binary(start, end, xor_pattern, 16, idc.SEARCH_DOWN) xor_fun_addr = idaapi.get_func(xor_fun_addr).start_ea print('[*] Traget fucntion found at {}'.format(hex(xor_fun_addr))) for ref in idautils.XrefsTo(xor_fun_addr): addr = ref.frm key, data, length = getData(addr) decrypt_string = Xor(key, data, length) idc.set_cmt(addr, decrypt_string, 1) ea = idc.next_head(idc.next_head(addr, end),end) global_var = idc.get_operand_value(ea, 0) idc.set_name(global_var, "Str_" + sanitize_string(decrypt_string), SN_NOWARN) def Anit_Reverse(): ea = 0 while True: ea = min(ida_search.find_binary(ea, idc.BADADDR, "74 ? 75 ?", 16, idc.SEARCH_NEXT | idc.SEARCH_DOWN), # JZ / JNZ ida_search.find_binary(ea, idc.BADADDR, "75 ? 74 ?", 16, idc.SEARCH_NEXT | idc.SEARCH_DOWN)) # JNZ / JZ if ea == idc.BADADDR: break idc.patch_byte(ea, 0xEB) idc.patch_byte(ea + 2, 0x90) idc.patch_byte(ea + 3, 0x90) idc.patch_byte(ea + 4, 0x90) def main(): Anit_Reverse() Strings_resolve(start,end) API_resolve(start,end) main() https://x-junior.github.io/malware%20analysis/2022/05/19/MarsStealer.html Page 30 of 32 for more Idapython scripts check my repo . IOCsPermalink Hashes: 1. md5 : 880924E5583978C615DD03FF89648093 2. sha1 : EF759F6ECA63D6B05A7B6E395DF3571C9703278B 3. sha256 : 4bcff4386ce8fadce358ef0dbe90f8d5aa7b4c7aec93fca2e605ca2cbc52218b 4. imphash : 4E06C011D59529BFF8E1F1C88254B928 5. ssdeep : 3072:U/E8k9fjpIg+zNch12KbAwSaSMtmSu4/bVBt4b8EG:U/E8k9bwz6/tJc/4xM8EG Mutex : 92550737836278980100 Files: 1. C:\ProgramData\freebl3.dll 2. C:\ProgramData\mozglue.dll 3. C:\ProgramData\msvcp140.dll 4. C:\ProgramData\nss3.dll 5. C:\ProgramData\softokn3.dll 6. C:\ProgramData\vcruntime140.dll C2 Server : 194.87.218.39 C2 Domains: 1. http://194[.]87[.]218[.]39/request 2. http://194[.]87[.]218[.]39/RyC66VfSGP[.]php YARAPermalink rule Mars_Stealer: Mars Stealer { meta: Author = "X__Junior" Description = "Mars Stealer v8 Detection" strings: $xor ={8b 4d ?? 03 4d ?? 0f be 19 8b 55 ?? 52 e8 ?? ?? ?? ?? 83 c4 ?? 8b c8 8b 45 ?? 33 d2 f7 f1 8b 45 ?? 0 $debug = {64 A1 30 00 00 00 80 78 02 00} $thread_func = {B8 01 00 00 00 85 ?? 74 ?? E8 ?? ?? ?? ?? 85 ?? 74 ?? 6A 00 FF ?? ?? ?? ?? ?? 6A ?? FF $api1 = "LocalAlloc" ascii $api2 = "VirtualProtect" ascii $api3 = "SetFileTime" ascii $api4 = "LocalFileTimeToFileTime" ascii $api5 = "HeapFree" ascii $api6 = "VirtualFree" ascii $api7 = "VirtualAlloc" ascii $s1 = "DPAPI" ascii $s2 = "memset" ascii https://x-junior.github.io/malware%20analysis/2022/05/19/MarsStealer.html Page 31 of 32 $s3 = "msvcrt.dll" ascii $s4 = "_mbsnbcpy" ascii $s5 = "_mbsstr" ascii condition: uint16(0) == 0x5A4D and 2 of($api*) and 3 of($s*) and $debug and $xor and $thread_func } ConclusionPermalink The last sample of mars i saw came packed with custom packer , easy to unpack with x32dbg by just setting a breakpoint on VirtualAlloc() , nothing else was changed except for the C2 . ReferencesPermalink Great analysis of the previous version https://3xp0rt.com/posts/mars-stealer https://lp.cyberark.com/rs/316-CZP-275/images/CyberArk-Labs-Racoon-Malware-wp.pdf Source: https://x-junior.github.io/malware%20analysis/2022/05/19/MarsStealer.html https://x-junior.github.io/malware%20analysis/2022/05/19/MarsStealer.html Page 32 of 32