Created
March 10, 2019 02:54
-
-
Save keyboardcrunch/c80c87cf563b8f575ae9e7ecb1f0487c to your computer and use it in GitHub Desktop.
repurposed chrome extension download and extraction script
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python3 | |
# -*- coding: utf-8 -*- | |
""" | |
Python Script to download the Chrome Extensions (CRX) file directly from the google chrome web store. | |
Referred from http://chrome-extension-downloader.com/how-does-it-work.php | |
""" | |
import argparse | |
import requests | |
import urllib.parse | |
import sys | |
import os | |
import fnmatch | |
import zipfile | |
__author__ = 'arul' | |
class ChromeAppDownloader(): | |
CRX_URL = "https://clients2.google.com/service/update2/crx?" \ | |
"response=redirect&prodversion=38.0&x=id%3D~~~~%26installsource%3Dondemand%26uc" | |
USER_AGENT = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.111 Safari/537.36" | |
global headers | |
headers = { | |
"User-Agent": USER_AGENT, | |
"Referer": "https://chrome.google.com", | |
} | |
def __init__(self): | |
pass | |
def download(self, _download_url_, _file_name_): | |
""" | |
Download the given URL into given filename. | |
:param _download_url_: | |
:param _file_name_: | |
:return: | |
""" | |
try: | |
# Download as Stream | |
r = requests.get(url=_download_url_, headers=headers, stream=True) | |
redirects = r.history | |
if len(redirects) > 0: | |
redirect_header = redirects[-1].headers | |
if "location" in redirect_header: | |
loc = redirect_header["location"] | |
uparse = urllib.parse.urlparse(loc) | |
splits = uparse.path.split("/") | |
_fname_ = splits[-1] | |
if _fname_: | |
_file_name_ = _fname_.replace("extension", _file_name_) | |
else: | |
_file_name_ += ".crx" | |
chunk_size = 16 * 1024 | |
dowloaded_bytes = 0 | |
with open(_file_name_, 'wb') as fd: | |
for chunk in r.iter_content(chunk_size): | |
fd.write(chunk) | |
return _file_name_ | |
except Exception as e: | |
raise ValueError("Error in downloading %s " % _download_url_, e) | |
def parse(self, chrome_store_url): | |
""" | |
Validate the given input is chrome store URL or not. | |
Returning app ID and app Name from the URL | |
:param chrome_store_url: | |
:return: | |
""" | |
try: | |
# Try to validate the URL | |
uparse = urllib.parse.urlparse(chrome_store_url) | |
if uparse.netloc != "chrome.google.com": | |
raise ValueError("Not a valid URL %s" % chrome_store_url) | |
splits = uparse.path.split("/") | |
if not (len(splits) == 4 and uparse.path.startswith("/webstore/detail/")): | |
raise ValueError("Not a valid URL %s" % chrome_store_url) | |
except Exception as e: | |
pass | |
return splits[-1], splits[-2] | |
if __name__ == '__main__': | |
# Getting webstore URL from User | |
parser = argparse.ArgumentParser(description='Download CRX file from Google Chrome Webstore.') | |
parser.add_argument('-u', '--url', help='URL of the chrome store', required=True) | |
args = parser.parse_args() | |
downloader = ChromeAppDownloader() | |
try: | |
file_name = None | |
# Validating and building app ID, file name for the given URL | |
chrome_app_id, file_name = downloader.parse(chrome_store_url=args.url) | |
if chrome_app_id: | |
download_url = downloader.CRX_URL.replace("~~~~", chrome_app_id) | |
# Downloading the CRX file | |
extension_file = downloader.download(download_url, file_name) | |
# Grab downloaded .crx, strip first 307 bytes and write to zip removing crx file | |
f = open(extension_file, 'rb') | |
f.seek(307) # skip first x bytes | |
zipcontent = f.read() | |
zip_name = extension_file.replace("crx", "zip") | |
open(zip_name, "wb").write(zipcontent) | |
os.remove(extension_file) | |
# extract content | |
zip_path = zip_name.replace(".zip", "") | |
with zipfile.ZipFile(zip_name, 'r') as zip_ref: | |
zip_ref.extractall(zip_path) | |
except Exception as e: | |
print(e) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment