You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
ORPA-pyOpenRPA/Sources/pyOpenRPA/Tools/SafeSource/DistrRun.py

161 lines
6.3 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#coding=utf-8
import os
import sys
import imp
import base64
from . import Crypter # Crypto functions
import datetime #Datetime
import hashlib #Get hash of the word
import pyautogui
EXT = '.cry'
# How to run
# sys.meta_path.append(Base64Importer(root_pkg_path))
# Init cryptographer
def CryptographerInit(inFolderPath):
sys.meta_path.append(Base64Importer(inFolderPath))
#===============================================================================
class Base64Importer(object):
"""Служит для поиска и импорта python-модулей, кодированных в base64
Класс реализует Import Protocol (PEP 302) для возможности импортирования
модулей, зашифрованных в base64 из указанного пакета.
"""
#---------------------------------------------------------------------------
def __init__(self, root_package_path, inKey):
self.mKeyStr = inKey
self.__modules_info = self.__collect_modules_info(root_package_path)
#---------------------------------------------------------------------------
def find_module(self, fullname, path=None):
"""Метод будет вызван при импорте модулей
Если модуль с именем fullname является base64 и находится в заданной
папке, данный метод вернёт экземпляр импортёра (finder), либо None, если
модуль не является base64.
"""
if fullname in self.__modules_info:
return self
return None
#---------------------------------------------------------------------------
def load_module(self, fullname):
"""Метод загружает base64 модуль
Если модуль с именем fullname является base64, то метод попытается его
загрузить. Возбуждает исключение ImportError в случае любой ошибки.
"""
if not fullname in self.__modules_info:
raise ImportError(fullname)
# Для потокобезопасности
imp.acquire_lock()
try:
mod = sys.modules.setdefault(fullname, imp.new_module(fullname))
mod.__file__ = "<{}>".format(self.__class__.__name__)
mod.__loader__ = self
if self.is_package(fullname):
mod.__path__ = []
mod.__package__ = fullname
else:
mod.__package__ = fullname.rpartition('.')[0]
src = self.get_source(fullname)
try:
exec(src) in mod.__dict__
except:
del sys.modules[fullname]
raise ImportError(fullname)
finally:
imp.release_lock()
return mod
#---------------------------------------------------------------------------
def is_package(self, fullname):
"""Возвращает True если fullname является пакетом
"""
return self.__modules_info[fullname]['ispackage']
#---------------------------------------------------------------------------
def get_source(self, fullname):
"""Возвращает исходный код модуля fullname в виде строки
Метод декодирует исходные коды из base64
"""
filename = self.__modules_info[fullname]['filename']
try:
src = Crypter.decrypt_file_bytes(key = self.mKeyStr, in_filename = filename).decode("utf-8")
#with open(filename, 'r') as ifile:
# src = base64.decodestring(ifile.read())
except IOError:
src = ''
return src
# for __main__
def get_code(self, inModName):
return self.get_source(inModName)
#---------------------------------------------------------------------------
def __collect_modules_info(self, root_package_path):
"""Собирает информацию о модулях из указанного пакета
"""
modules = {}
p = os.path.abspath(root_package_path)
dir_name = os.path.dirname(p) + os.sep
for root, _, files in os.walk(p):
# Информация о текущем пакете
filename = os.path.join(root, '__init__' + EXT)
p_fullname = root.rpartition(dir_name)[2].replace(os.sep, '.')
modules[p_fullname] = {
'filename': filename,
'ispackage': True
}
# Информация о модулях в текущем пакете
for f in files:
if not f.endswith(EXT):
continue
filename = os.path.join(root, f)
fullname = '.'.join([p_fullname, os.path.splitext(f)[0]])
modules[fullname] = {
'filename': filename,
'ispackage': False
}
return modules
# Settings
gInUncryptedExtension = "py" # cry for filename.cry
gOutCryptedExtension = "cry" # cry for filename.cry
gFileMaskToDelete = "pyc" #Remove all .pyc files
#Settings to run crypted module
gSettings = {
#runpy
"run_module": {
"mod_name": "TestPackage", #"TestPackage",
"init_globals": None,
"run_name": None,
"alter_sys": True
}
}
# Create process run
def Run():
global gSettings
print(f"{str(datetime.datetime.now())}: Run decryptography")
############# Step 5 - Ask and confirm the secret word
lKeyHashStr_1 = hashlib.sha256(pyautogui.password('Please enter the key to protect source code').encode("utf-8")).digest()
lKeyHashStr_2 = hashlib.sha256(pyautogui.password('Please repeat the key to protect source code').encode("utf-8")).digest()
if lKeyHashStr_1 == lKeyHashStr_2:
sys.meta_path.append(Base64Importer("TestPackage",inKey = lKeyHashStr_1))
#CryptographerInit("", inKey = lKeyHashStr_1)
#Init the functions
import runpy
runpy.run_module(**gSettings["run_module"])
else:
raise Exception("User set different secret key 1 and key 2")
############ Step 6 - Final stage
print(f"{str(datetime.datetime.now())}: Cryprography module has been successfully initialized")